vrpRouting  0.3
fleet.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 
3 FILE: fleet.h
4 
5 Copyright (c) 2017 pgRouting developers
7 
8 ------
9 
10 Vhis 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 Vhis program is distributed in the hope that it will be useful,
16 but WIVHOUV ANY WARRANVY; without even the implied warranty of
17 MERCHANVABILIVY or FIVNESS FOR A PARVICULAR 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 
28 #include "problem/fleet.h"
29 
30 #include <iostream>
31 #include <vector>
32 #include <numeric>
33 #include <limits>
34 #include <utility>
35 #include <algorithm>
36 
37 #include "c_types/vehicle_t.h"
38 
39 namespace vrprouting {
40 namespace problem {
41 
42 void
44  m_msg.log << "\n used v" << m_used;
45  m_msg.log << "\n not used v" << m_unused;
46  pgassertwm(m_size == size(), m_msg.get_log());
47  auto m_total = m_used + m_unused + m_invalid;
48  pgassertwm(m_total.size() == size(), m_msg.get_log());
49  for (const auto &e : m_used) {
50  pgassertwm(e < size(), m_msg.get_log());
51  }
52  for (const auto &e : m_unused) {
53  pgassertwm(e < size(), m_msg.get_log());
54  }
55  for (const auto &e : m_invalid) {
56  pgassertwm(e < size(), m_msg.get_log());
57  }
58 }
59 
63 std::vector<Vehicle_pickDeliver>
65  invariant();
66  std::vector<Vehicle_pickDeliver> trucks;
67  for (auto v_idx : m_used) {
68  if (!at(v_idx).is_phony()) {
69  trucks.push_back(at(v_idx));
70  }
71  }
72  invariant();
73  return trucks;
74 }
75 
79 std::vector<Vehicle_pickDeliver>
81  ENTERING(m_msg);
82  invariant();
83  std::vector<Vehicle_pickDeliver> trucks;
84  m_msg.log << "fleet size" << size();
85  m_msg.log << m_unused;
86  for (auto v_idx : m_unused) {
87  pgassertwm(v_idx < size(), m_msg.get_log());
88  if (!at(v_idx).is_phony()) {
89  trucks.push_back(at(v_idx));
90  }
91  }
92  invariant();
93  return trucks;
94 }
95 
98  invariant();
99  return std::accumulate(this->begin(), this->end(), Identifiers<size_t>(),
100  [](Identifiers<size_t> i, const Vehicle_pickDeliver& v) {return v.feasible_orders() + i;});
101 }
102 
106 void
108  pgassert(m_used.size() == 0);
109  pgassert(m_unused.size() == size());
110  pgassert(m_invalid.size() == 0);
111  for (auto &v : *this) {
112  if (!v.is_ok()) {
113  m_invalid += v.idx();
114  m_unused -= v.idx();
115  }
116  }
117  invariant();
118 }
119 
122  auto idx = m_unused.front();
123  m_used += idx;
124  if (this->size() > 1) m_unused -= idx;
125  return at(idx);
126 }
127 
132 Fleet::get_truck(size_t order_idx) {
133  for (const auto &idx : m_unused) {
134  if (at(idx).feasible_orders().has(order_idx)) {
135  m_used += idx;
136  if (m_unused.size() > 1) m_unused -= idx;
137  return at(idx);
138  }
139  }
140  return at(m_unused.back());
141 }
142 
143 bool
145  ENTERING(m_msg);
146  if (!m_msg.get_error().empty()) return false;
147  for (auto truck : *this) {
148  if (!truck.is_ok()) {
149  m_msg.error << "Illegal values found on vehicle";
150  m_msg.log << "On vehicle " << truck.id()
151  << " a condition is not met, verify that:\n"
152  << "- start_open <= start_close\n"
153  << "- end_open <= end_close\n"
154  << "- capacity > 0\n";
155  return false;
156  }
157 
158  if (!(truck.start_site().is_start()
159  && truck.end_site().is_end())) {
160  pgassertwm(false, "should never pass through here");
161  m_msg.error << "Illegal values found on vehicle";
162  return false;
163  }
164  if (!truck.is_feasible()) {
165  m_msg.error << "Truck is not feasible";
166  return false;
167  }
168  }
169  EXITING(m_msg);
170  return true;
171 }
172 
178 bool
179 Fleet::is_order_ok(const Order &order) const {
180  for (const auto &truck : *this) {
181  if (!order.is_valid(truck.speed())) continue;
182  if (truck.is_order_feasible(order)) {
183  return true;
184  }
185  }
186  return false;
187 }
188 
195 void
197  const Vehicle_t &vehicle,
198  const std::vector<Short_vehicle>& new_stops,
199  const Orders& p_orders,
200  std::vector<Vehicle_node>& p_nodes,
201  size_t& node_id) {
202 
206  if ((vehicle.start_close_t < vehicle.start_open_t)
207  || (vehicle.end_close_t < vehicle.end_open_t)
208  // || (vehicle.capacity < 0) // the comparison of unsigned expression < 0 is always false
209  ) {
210  m_msg.error << "Illegal values found on vehicle";
211  m_msg.log << "On vehicle " << vehicle.id
212  << " a condition is not met:\n"
213  << "verify that:\n"
214  << "- start_open <= start_close: "
215  << vehicle.start_open_t << "<" << vehicle.start_close_t << "\n"
216  << "- end_open <= end_close: "
217  << vehicle.end_open_t << "<" << vehicle.end_close_t << "\n"
218  << "- capacity > 0" << vehicle.capacity << "\n";
219  throw std::make_pair(m_msg.get_error(), msg().get_log());
220  return;
221  }
222 
226  auto starting_site = Vehicle_node({node_id++, vehicle, NodeType::kStart});
227  auto ending_site = Vehicle_node({node_id++, vehicle, NodeType::kEnd});
228 
229  pgassert(starting_site.is_start() && ending_site.is_end());
230 
234  p_nodes.push_back(starting_site);
235  p_nodes.push_back(ending_site);
236 
237  auto v_id = vehicle.id;
238  auto vehicle_new_stops_ptr = std::find_if(new_stops.begin(), new_stops.end(), [v_id]
239  (const Short_vehicle& v) -> bool {return v.id == v_id;});
240  bool replace_stops = vehicle_new_stops_ptr != new_stops.end();
241 
245  for (Amount i = 0; i < vehicle.cant_v; ++i) {
246  if (replace_stops) {
247  this->emplace_back(
248  this->size(),
249  vehicle.id,
250  starting_site,
251  ending_site,
252  /*
253  * stops can only be assigned when there is only one vehicle
254  */
255  vehicle.cant_v == 1? vehicle_new_stops_ptr->stops : std::vector<int64_t>(),
256  vehicle.capacity,
257  vehicle.speed,
258  p_orders);
259  } else {
260  this->emplace_back(
261  this->size(),
262  vehicle.id,
263  starting_site,
264  ending_site,
265  /*
266  * stops can only be assigned when there is only one vehicle
267  */
268  vehicle.cant_v == 1 ?
269  std::vector<int64_t>(vehicle.stops, vehicle.stops + vehicle.stops_size) :
270  std::vector<int64_t>(),
271 
272  vehicle.capacity,
273  vehicle.speed,
274  p_orders);
275  }
276  }
277 }
278 
279 
295 void
297  const Orders &orders,
298  Identifiers<size_t>& assigned,
299  Identifiers<size_t>& unassigned,
300  TTimestamp execution_date,
301  bool optimize) {
302  for (auto &v : *this) {
306  v.set_initial_solution(orders, assigned, unassigned, execution_date, optimize);
307  }
308 }
312 void
317  for (const auto &o : orders) {
321  for (auto & m_vehicle : *this) {
325  if (m_vehicle.end_site().closes() < o.pickup().opens()) continue;
326 
330  if (o.delivery().closes() < m_vehicle.start_site().opens()) continue;
331 
332  if (m_vehicle.is_order_feasible(o)) {
333  m_msg.log << "Order " << o.id() << "is feasible on Vehicle " << m_vehicle.id() <<"\n";
334  auto test_truck = m_vehicle;
335  test_truck.push_back(o);
336  m_msg.log << test_truck;
337 
341  m_vehicle.feasible_orders() += o.idx();
342  }
343  }
344 
348  if (at(this->size() - 1).is_order_feasible(o)) {
349  at(this->size() - 1).feasible_orders() += o.idx();
350  }
351  }
352 }
353 
363 void
365  Vehicle_t *vehicles, size_t size_vehicles,
366  const std::vector<Short_vehicle>& new_stops,
367  const Orders& p_orders,
368  std::vector<Vehicle_node>& p_nodes,
369  size_t& node_id) {
373  std::sort(vehicles, vehicles + size_vehicles,
374  [] (const Vehicle_t &lhs, const Vehicle_t &rhs) {
375  if (lhs.start_open_t == rhs.start_open_t) {
376  if (lhs.end_close_t == rhs.end_close_t) {
377  return lhs.id < rhs.id;
378  } else {
379  return lhs.end_close_t < rhs.end_close_t;
380  }
381  } else {
382  return lhs.start_open_t < rhs.start_open_t;
383  }
384  });
385 
389  for (size_t i = 0; i < size_vehicles; ++i) {
390  add_vehicle(vehicles[i], new_stops, p_orders, p_nodes, node_id);
391  }
396  Vehicle_t phony_v({
397  /*
398  * id, capacity
399  */
400  -1,
401  (std::numeric_limits<PAmount>::max)(),
402  vehicles[0].speed,
403  1,
404  nullptr,
405  0,
406 
407  /*
408  * Start values
409  */
410  vehicles[0].start_node_id,
411  0,
412  (std::numeric_limits<TTimestamp>::max)(),
413  0,
414  vehicles[0].start_x,
415  vehicles[0].start_y,
416 
417  /*
418  * End values
419  */
420  vehicles[0].end_node_id,
421  0,
422  (std::numeric_limits<TTimestamp>::max)(),
423  0,
424  vehicles[0].end_x,
425  vehicles[0].end_y,
426  });
427 
428  /*
429  * Add the phony vehicle
430  */
431  add_vehicle(phony_v, new_stops, p_orders, p_nodes, node_id);
432 
433  Identifiers<size_t> unused(this->size());
434  m_size = size();
435  m_unused = unused;
436  pgassert(m_unused.size() == size());
437  invariant();
438 }
439 
440 } // namespace problem
441 } // namespace vrprouting
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::problem::Fleet::is_fleet_ok
bool is_fleet_ok() const
Definition: fleet.cpp:144
Vehicle_t::stops
Id * stops
Number of vehicles with same description.
Definition: vehicle_t.h:55
vehicle_t.h
vrprouting::problem::kStart
@ kStart
starting site
Definition: node_types.h:36
vrprouting::problem::Fleet::get_used_trucks
std::vector< Vehicle_pickDeliver > get_used_trucks()
Get all the used vehicles.
Definition: fleet.cpp:64
vrprouting::problem::Fleet::set_initial_solution
void set_initial_solution(const Orders &, Identifiers< size_t > &, Identifiers< size_t > &, TTimestamp, bool)
set the vehicle's user's initial solution
Definition: fleet.cpp:296
vrprouting::problem::Fleet::get_truck
Vehicle_pickDeliver get_truck()
Finds an unused vehicle.
Definition: fleet.cpp:121
ENTERING
#define ENTERING(x)
Definition: pgr_messages.h:104
pgassertwm
#define pgassertwm(expr, msg)
Adds a message to the assertion.
Definition: pgr_assert.h:118
vrprouting::Pgr_messages::error
std::ostringstream error
Stores the error information.
Definition: pgr_messages.h:95
Vehicle_t
vehicles's attributes
Definition: vehicle_t.h:50
Vehicle_t::start_open_t
TTimestamp start_open_t
Start node's identifier.
Definition: vehicle_t.h:59
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:95
vrprouting::problem::Orders
Definition: orders.h:48
Vehicle_t::end_open_t
TTimestamp end_open_t
End node's identifier.
Definition: vehicle_t.h:66
vrprouting::problem::Fleet::m_used
Identifiers< size_t > m_used
set of used vehicles
Definition: fleet.h:144
Identifiers::size
size_t size() const
Definition: identifiers.hpp:77
vrprouting::problem::Fleet::m_size
size_t m_size
Definition: fleet.h:155
vrprouting::problem::Fleet::is_order_ok
bool is_order_ok(const Order &order) const
Given an order, Cycle trhugh all the trucks to verify if the order can be served by at least one truc...
Definition: fleet.cpp:179
Short_vehicle
short_vehicle
Definition: short_vehicle.h:41
vrprouting::problem::Fleet::set_compatibles
void set_compatibles(const Orders &orders)
sets the compatability of orders on the fleet
Definition: fleet.cpp:313
vrprouting::Pgr_messages::get_log
std::string get_log() const
gets the contents of log message
Definition: pgr_messages.cpp:36
vrprouting::problem::Vehicle_node
Extend Tw_node to evaluate the vehicle at node level.
Definition: vehicle_node.h:49
vrprouting::problem::Fleet::feasible_orders
Identifiers< size_t > feasible_orders() const
Definition: fleet.cpp:97
vrprouting::problem::Vehicle_pickDeliver
Definition: vehicle_pickDeliver.h:46
Vehicle_t::start_close_t
TTimestamp start_close_t
Start open time.
Definition: vehicle_t.h:60
vrprouting::problem::kEnd
@ kEnd
ending site
Definition: node_types.h:41
Identifiers::back
T back() const
Definition: identifiers.hpp:80
vrprouting::problem::Fleet::m_unused
Identifiers< size_t > m_unused
set of unused vehicles
Definition: fleet.h:147
Vehicle_t::speed
Speed speed
Vehicle's capacity.
Definition: vehicle_t.h:53
TTimestamp
int64_t TTimestamp
Definition: typedefs.h:71
vrprouting::problem::Fleet::m_msg
Pgr_messages m_msg
Definition: fleet.h:152
Amount
int64_t Amount
Definition: typedefs.h:74
vrprouting::problem::Fleet::invariant
void invariant() const
Definition: fleet.cpp:43
vrprouting::Pgr_messages::get_error
std::string get_error() const
gets the contents of error message
Definition: pgr_messages.cpp:53
vrprouting::problem::Order::is_valid
bool is_valid(Speed speed=1.0) const
is the order valid?
Definition: order.cpp:109
vrprouting::problem::Fleet::add_vehicle
void add_vehicle(const Vehicle_t &, const std::vector< Short_vehicle > &, const Orders &, std::vector< Vehicle_node > &p_nodes, size_t &node_id)
add a new vehicle to the fleet
Definition: fleet.cpp:196
Identifiers::front
T front() const
Definition: identifiers.hpp:79
vrprouting::problem::Tw_node::is_end
bool is_end() const
Is the node a valid vehicle's ending node.
Definition: tw_node.cpp:245
Vehicle_t::end_close_t
TTimestamp end_close_t
End open time.
Definition: vehicle_t.h:67
Vehicle_t::capacity
PAmount capacity
Vehicle's identifier.
Definition: vehicle_t.h:52
Vehicle_t::cant_v
PAmount cant_v
Definition: vehicle_t.h:54
vrprouting::problem::Fleet::build_fleet
void build_fleet(Vehicle_t *, size_t, const std::vector< Short_vehicle > &, const Orders &, std::vector< Vehicle_node > &p_nodes, size_t &node_id)
build the fleet
Definition: fleet.cpp:364
vrprouting::problem::Fleet::msg
Pgr_messages & msg()
Definition: fleet.h:126
Vehicle_t::stops_size
size_t stops_size
Stops.
Definition: vehicle_t.h:56
vrprouting::problem::Order
Definition: order.h:40
vrprouting::problem::Fleet::m_invalid
Identifiers< size_t > m_invalid
set of invalid vehicles
Definition: fleet.h:150
vrprouting::problem::Fleet::clean
void clean()
removes from fleet all invalid vehicles
Definition: fleet.cpp:107
Vehicle_t::id
Id id
Definition: vehicle_t.h:51
vrprouting::problem::Fleet::get_unused_trucks
std::vector< Vehicle_pickDeliver > get_unused_trucks()
Get all the unused vehicles.
Definition: fleet.cpp:80
Identifiers< size_t >
vrprouting
Definition: base_matrix.cpp:46
fleet.h