vrpRouting  0.3
vehicle_pickDeliver.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 
3 FILE: vehicle_pickDeliver.h
4 
5 Copyright (c) 2016 pgRouting developers
7 
8 ------
9 
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 
24  ********************************************************************PGR-GNU*/
25 
29 
30 #include <limits>
31 #include <utility>
32 #include <vector>
33 
34 #include "problem/vehicle.h"
35 #include "problem/order.h"
36 #include "problem/orders.h"
37 
38 namespace vrprouting {
39 namespace problem {
40 
41 
56 void
58  pgassert(!has_order(order));
59  m_orders_in_vehicle += order.idx();
60  insert_node(size() - 1, order.pickup());
61  insert_node(size() - 1, order.delivery());
62  evaluate(size() - 3);
63  pgassert(has_order(order));
64 }
65 
83 void
85  pgassert(!has_order(order));
86  m_orders_in_vehicle += order.idx();
87  insert_node(1, order.delivery());
88  insert_node(1, order.pickup());
89  evaluate();
90  pgassert(has_order(order));
91 }
92 
93 
94 size_t
96  invariant();
97  pgassert(!empty());
98 
99  auto pick_itr = rbegin();
100  while (pick_itr != rend() && !pick_itr->is_pickup()) {
101  ++pick_itr;
102  }
103 
104  pgassert(pick_itr->is_pickup());
105 
106  auto deleted_pick_idx = pick_itr->idx();
107 
108  for (const auto &o : this->orders()) {
109  if (o.pickup().idx() == deleted_pick_idx) {
110  erase(o);
111  invariant();
112  return o.idx();
113  }
114  }
115  pgassert(false);
116  return 0;
117 }
118 
119 
120 size_t
122  invariant();
123  pgassert(!empty());
124 
125  auto pick_itr = begin();
126  while (pick_itr != end() && !pick_itr->is_pickup()) {
127  ++pick_itr;
128  }
129 
130  pgassert(pick_itr->is_pickup());
131 
132  auto deleted_pick_idx = pick_itr->idx();
133 
134  for (const auto &o : this->orders()) {
135  if (o.pickup().idx() == deleted_pick_idx) {
136  erase(o);
137  invariant();
138  return o.idx();
139  }
140  }
141 
142  pgassert(false);
143  return 0;
144 }
145 
153 void
155  pgassert(has_order(order));
156  erase(order.pickup());
157  erase(order.delivery());
158  m_orders_in_vehicle -= order.idx();
159  pgassert(!has_order(order));
160 }
161 
170 void
172  const Orders &orders,
173  Identifiers<size_t>& assigned,
174  Identifiers<size_t>& unassigned,
175  TTimestamp execution_date,
176  bool optimize) {
180  pgassert(this->m_user_twv == 0);
181  pgassert(this->m_user_cv == 0);
182 
186  if (m_stops.empty()) return;
187  std::vector<size_t> stops;
188 #if 1
189  msg().log << "\n******\n" << this->id() << "\t stops(o_id) -> ";
190  for (const auto &s : m_stops) {
191  msg().log << s << ", ";
192  }
193 #endif
194 
195 
196  Identifiers<size_t> picked_orders;
197  size_t i(0);
201  for (const auto o_id : m_stops) {
205  auto order = std::find_if(orders.begin(), orders.end(), [o_id]
206  (const Order& o) -> bool {
207  return o.id() == o_id;
208  });
209 
210  pgassert(order != orders.end());
211 
212  if (assigned.has(order->idx())) {
213  pgassertwm(false, "Assigning an order twice");
214  }
215 
216  stops.push_back(order->idx());
217  if (picked_orders.has(order->idx())) {
221  insert(i + 1, order->delivery());
222  picked_orders -= order->idx();
223  m_orders_in_vehicle += order->idx();
224  assigned += order->idx();
225  unassigned -= order->idx();
226  } else {
230  insert(i + 1, order->pickup());
231  picked_orders += order->idx();
232  }
233  ++i;
234  }
235  evaluate();
236  set_unmovable(execution_date);
237 
238 #if 1
239  msg().log << "\n" << this->id() << "\t (idx,id) -> ";
240  for (const auto &s : stops) {
241  msg().log << "(" << s << ", " << orders[s].id() << ")";
242  }
243 #endif
244 
248  if (!is_feasible()) {
249  msg().log << "\n**********************************Vehicle is not feasible with initial orders";
250  msg().log << "twvTot " << this->twvTot() << "\tm_user_twv" << this->m_user_twv << "\n";
251  msg().log << "cvTot " << this->cvTot() << "\tm_user_cv" << this->m_user_cv << "\n";
252  msg().log << "\nVehicle: " << this->id() << "Orders: ";
253  for (const auto &s : m_stops) msg().log << s << ",";
254  msg().log << "\n";
255  msg().log << "\n" << *this;
256 
257 
258 
259  if (optimize) {
260  auto orders_to_remove = m_orders_in_vehicle;
264  for (const auto o : orders_to_remove) {
265  auto order = this->orders();
266  erase(this->orders()[o]);
267  m_orders_in_vehicle -= o;
268  assigned -= o;
269  unassigned += o;
270  }
271  }
272  this->m_user_twv = this->twvTot();
273  this->m_user_cv = this->cvTot();
274  }
275 
280  msg().log << "\n" << this->tau();
281 }
282 
291 void
293  Identifiers<size_t> unmovable;
294  msg().log << "\nVehicle: " << this->id() << "unmovable: {";
295  for (const auto &o : m_orders_in_vehicle) {
296  for (const auto &s : *this) {
297  auto order = this->orders()[o];
298 
299  if (s.order() == order.id() && s.is_pickup()) {
300  if (s.opens() < execution_date) {
301  unmovable += o;
302  msg().log << order.id() << ",";
303  }
304  }
305  }
306  }
307 
308  msg().log << "}";
309 
313  m_orders_in_vehicle -= unmovable;
314 }
315 
322  return is_phony()?
323  0 :
324  static_cast<double>(total_travel_time());
325 }
326 
333 bool
335  auto test_truck = *this;
336  test_truck.push_back(order);
337  return test_truck.is_feasible();
338 }
339 
360 bool
362  invariant();
363  pgassert(!has_order(order));
364 
365  /*
366  * Insert pick up as first picked
367  */
368  insert(1, order.pickup());
369 
370  auto deliver_pos(drop_position_limits(order.delivery()));
371 
372  /*
373  * delivery generates twv in all positions
374  */
375  if (deliver_pos.second < deliver_pos.first) {
376  /*
377  * Remove inserted pickup
378  */
379  erase(1);
380  invariant();
381  return false;
382  }
383 
384  pgassert(!has_order(order));
385  while (deliver_pos.first <= deliver_pos.second) {
386  insert(deliver_pos.second, order.delivery());
387 
388  if (is_feasible() && !at(deliver_pos.second + 1).is_pickup()) {
389  /*
390  * Found a position to insert the delivery
391  */
392 
393 
394  m_orders_in_vehicle += order.idx();
395 
396  /*
397  * There is one more order in the vehicle
398  */
399  pgassert(has_order(order));
401  pgassert(!has_cv());
402  pgassert(!has_twv());
403  pgassert(has_order(order));
404  invariant();
405  return true;
406  }
407 
408  /*
409  * This position in path is not suitable
410  */
411  erase(deliver_pos.second);
412 
413  /*
414  * got to next position
415  */
416  --deliver_pos.second;
417  }
418 
419  /*
420  * Order could not be inserted
421  */
422  erase(1);
423 
424  pgassert(!has_order(order));
425  invariant();
426  return false;
427 }
428 
443 bool
448  invariant();
449  pgassert(!has_order(order));
450 
451  auto pick_pos(position_limits(order.pickup()));
452  auto deliver_pos(position_limits(order.delivery()));
453 
454  if (pick_pos.second < pick_pos.first) {
455  /*
456  * pickup generates twv everywhere
457  */
458  return false;
459  }
460 
461  if (deliver_pos.second < deliver_pos.first) {
462  /*
463  * delivery generates twv everywhere
464  */
465  return false;
466  }
467  /*
468  * Because delivery positions were estimated without the pickup:
469  * - increase the upper limit position estimation
470  */
471  ++deliver_pos.first;
472  ++deliver_pos.second;
473 
474 
475  auto best_pick_pos = size();
476  auto best_deliver_pos = size() + 1;
477  auto current_objective(objective());
478  auto min_delta_objective = (std::numeric_limits<double>::max)();
479 
480  auto found(false);
481 
482  // insert order.pickup() (that is, the order pickup node) into the earliest possible pick position
483  insert(pick_pos.first, order.pickup());
484 
485  // while the pick is < latest pick
486  while (pick_pos.first <= pick_pos.second) {
487  auto deliver_range = deliver_pos;
488  if (deliver_range.first <= pick_pos.first) deliver_range.first = pick_pos.first + 1;
489 
490  /*
491  * hill climb
492  * - find the best position
493  * finds the best position based on objective.
494  */
495  insert(deliver_range.first, order.delivery());
496  while (deliver_range.first <= deliver_range.second) {
497  if (is_feasible()) {
498  auto delta_objective = objective() - current_objective;
499  if (delta_objective < min_delta_objective) {
500  min_delta_objective = delta_objective;
501  best_pick_pos = pick_pos.first;
502  best_deliver_pos = deliver_range.first;
503  found = true;
504  }
505  }
506  if (at(deliver_range.first + 1).is_end()) break;
507  swap(deliver_range.first, deliver_range.first + 1);
508  ++deliver_range.first;
509  }
510 
511  pgassert(at(deliver_range.first).order() == order.id());
512  pgassert(at(pick_pos.first).order() == order.id());
513  erase_node(deliver_range.first);
514 
515  if (at(pick_pos.first + 1).is_end()) break;
516 
517  swap(pick_pos.first, pick_pos.first + 1);
518 
519  ++pick_pos.first;
520  }
521  erase(pick_pos.first);
522 
523  if (!found) {
524  /* order causes twv or cv */
525  return false;
526  }
527 
531  insert(best_pick_pos, order.pickup());
532  insert(best_deliver_pos, order.delivery());
533  m_orders_in_vehicle += order.idx();
534 
539  invariant();
540  return true;
541 }
542 
543 
544 } // namespace problem
545 } // namespace vrprouting
546 
vrprouting::problem::Vehicle_pickDeliver::set_unmovable
void set_unmovable(TTimestamp execution_date)
sets as unmovable the orders that start before the execution date
Definition: vehicle_pickDeliver.cpp:292
vrprouting::problem::Vehicle_pickDeliver::erase
void erase(const Order &order)
erases the order from the vehicle
Definition: vehicle_pickDeliver.cpp:154
vrprouting::problem::Vehicle::twvTot
int twvTot() const
Definition: vehicle.cpp:92
vrprouting::problem::Vehicle::evaluate
void evaluate()
Definition: vehicle.cpp:126
vrprouting::Pgr_messages::log
std::ostringstream log
Stores the hint information.
Definition: pgr_messages.h:91
vrprouting::problem::Vehicle::invariant
void invariant() const
Definition: vehicle.cpp:100
vrprouting::Identifier::id
int64_t id() const
get the original id
Definition: identifier.cpp:42
vrprouting::problem::Vehicle_pickDeliver::pop_back
size_t pop_back()
Definition: vehicle_pickDeliver.cpp:95
vrprouting::problem::Vehicle_pickDeliver::hillClimb
bool hillClimb(const Order &order)
Inserts an order with hill Climb approach.
Definition: vehicle_pickDeliver.cpp:444
vrprouting::problem::Vehicle::has_twv
bool has_twv() const
Definition: vehicle.cpp:96
pgassertwm
#define pgassertwm(expr, msg)
Adds a message to the assertion.
Definition: pgr_assert.h:118
vrprouting::problem::Vehicle::m_user_cv
int m_user_cv
Time window violations on solution.
Definition: vehicle.h:179
vrprouting::problem::Vehicle_pickDeliver::m_stops
std::vector< int64_t > m_stops
order ids of an initial solution given by the user [1,2,1,3,3,2] = P1 P2 D1 P3 D3 D2
Definition: vehicle_pickDeliver.h:175
vrprouting::problem::Vehicle_pickDeliver::push_back
void push_back(const Order &order)
puts an order at the end of the truck
Definition: vehicle_pickDeliver.cpp:57
vrprouting::problem::Vehicle::is_phony
bool is_phony() const
Definition: vehicle.cpp:116
vrprouting::problem::Vehicle_pickDeliver::msg
Pgr_messages & msg()
Definition: vehicle_pickDeliver.h:150
vrprouting::problem::Vehicle::is_feasible
bool is_feasible() const
Definition: vehicle.cpp:120
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:95
vrprouting::problem::Orders
Definition: orders.h:48
vrprouting::problem::Vehicle_pickDeliver::objective
double objective() const
Get the value of the objective function.
Definition: vehicle_pickDeliver.cpp:321
vrprouting::problem::Vehicle_pickDeliver::m_orders_in_vehicle
Identifiers< size_t > m_orders_in_vehicle
orders inserted in this vehicle
Definition: vehicle_pickDeliver.h:161
vrprouting::problem::Vehicle_pickDeliver::has_order
bool has_order(const Order &order) const
does the vehicle has the order?
Definition: vehicle_pickDeliver.h:108
vrprouting::problem::Vehicle_pickDeliver::semiLIFO
bool semiLIFO(const Order &order)
Inserts an order In semi-Lifo (almost last in first out) order.
Definition: vehicle_pickDeliver.cpp:361
vrprouting::problem::Vehicle::m_user_twv
int m_user_twv
Time window violations on solution.
Definition: vehicle.h:173
vrprouting::problem::Vehicle_pickDeliver::orders
const Orders & orders() const
Definition: vehicle_pickDeliver.h:148
vrprouting::Identifier::idx
size_t idx() const
get the internal index
Definition: identifier.cpp:37
vrprouting::problem::Vehicle::swap
void swap(size_t i, size_t j)
Definition: vehicle.cpp:228
vrprouting::problem::Vehicle_pickDeliver::is_order_feasible
bool is_order_feasible(const Order &order) const
Definition: vehicle_pickDeliver.cpp:334
vrprouting::problem::Vehicle::cvTot
int cvTot() const
Definition: vehicle.cpp:94
vrprouting::problem::Order::pickup
const Vehicle_node & pickup() const
The pickup node identifier.
Definition: order.h:65
vrprouting::problem::Vehicle_pickDeliver::push_front
void push_front(const Order &order)
Puts an order at the end front of the truck.
Definition: vehicle_pickDeliver.cpp:84
TTimestamp
int64_t TTimestamp
Definition: typedefs.h:71
vehicle_pickDeliver.h
vehicle.h
Identifiers::has
bool has(const T other) const
true ids() has element
Definition: identifiers.hpp:100
vrprouting::problem::Vehicle::total_travel_time
TInterval total_travel_time() const
total time spent moving from one node to another
Definition: vehicle.cpp:84
vrprouting::problem::Vehicle::erase_node
void erase_node(size_t pos)
Definition: vehicle.cpp:152
vrprouting::problem::Vehicle::insert_node
void insert_node(size_t pos, const Vehicle_node &node)
Definition: vehicle.cpp:158
order.h
vrprouting::problem::Vehicle::tau
std::string tau() const
Definition: vehicle.cpp:251
orders.h
vrprouting::problem::Vehicle_pickDeliver::pop_front
size_t pop_front()
Definition: vehicle_pickDeliver.cpp:121
vrprouting::problem::Vehicle::has_cv
bool has_cv() const
Definition: vehicle.cpp:98
vrprouting::problem::Vehicle::drop_position_limits
std::pair< size_t, size_t > drop_position_limits(const Vehicle_node &node) const
Definition: vehicle.cpp:426
vrprouting::problem::Order
Definition: order.h:40
vrprouting::problem::Order::delivery
const Vehicle_node & delivery() const
The delivery node identifier.
Definition: order.h:68
vrprouting::problem::Vehicle::position_limits
std::pair< size_t, size_t > position_limits(const Vehicle_node &node) const
Get the limits to insert the node.
Definition: vehicle.cpp:419
vrprouting::problem::Vehicle_pickDeliver::set_initial_solution
void set_initial_solution(const Orders &, Identifiers< size_t > &, Identifiers< size_t > &, TTimestamp, bool)
sets the initial solution given by the user
Definition: vehicle_pickDeliver.cpp:171
Identifiers< size_t >
vrprouting::problem::Vehicle::insert
void insert(size_t pos, const Vehicle_node &node)
Definition: vehicle.cpp:202
vrprouting::problem::Vehicle::empty
bool empty() const
Definition: vehicle.cpp:112
vrprouting
Definition: base_matrix.cpp:46