vrpRouting  0.3
optimize_driver.cpp File Reference
#include "drivers/optimize_driver.h"
#include <cstring>
#include <sstream>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>
#include "problem/pickDeliver.h"
#include "c_types/pickDeliveryOrders_t.h"
#include "c_types/short_vehicle_rt.h"
#include "c_types/vehicle_t.h"
#include "problem/matrix.h"
#include "cpp_common/pgr_assert.h"
#include "cpp_common/pgr_messages.h"
#include "initialsol/tabu.h"
#include "optimizers/tabu.h"
#include "c_common/pgr_alloc.hpp"
#include "cpp_common/interruption.h"
Include dependency graph for optimize_driver.cpp:

Go to the source code of this file.

Namespaces

 anonymous_namespace{optimize_driver.cpp}
 

Functions

void do_optimize (PickDeliveryOrders_t *shipments_arr, size_t total_shipments, Vehicle_t *vehicles_arr, size_t total_vehicles, Matrix_cell_t *matrix_cells_arr, size_t total_cells, Time_multipliers_t *multipliers_arr, size_t total_multipliers, double factor, int max_cycles, int64_t execution_date, bool check_triangle_inequality, bool subdivide, bool subdivide_by_vehicle, Short_vehicle_rt **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)
 
std::vector< Short_vehicleanonymous_namespace{optimize_driver.cpp}::get_initial_stops (Vehicle_t *vehicles_arr, size_t total_vehicles)
 get the original stops More...
 
std::vector< Short_vehicleanonymous_namespace{optimize_driver.cpp}::one_processing (PickDeliveryOrders_t *shipments_arr, size_t total_shipments, Vehicle_t *vehicles_arr, size_t total_vehicles, std::vector< Short_vehicle > new_stops, const vrprouting::problem::Matrix &time_matrix, int max_cycles, int64_t execution_date)
 Executes an optimization with the input data. More...
 
Identifiers< TTimestampanonymous_namespace{optimize_driver.cpp}::processing_times_by_shipment (PickDeliveryOrders_t *shipments_arr, size_t total_shipments)
 : extract the times where the shipments opens or closes More...
 
Identifiers< TTimestampanonymous_namespace{optimize_driver.cpp}::processing_times_by_vehicle (Vehicle_t *vehicles_arr, size_t total_vehicles)
 : extract the times where the vehicle opens or closes More...
 
std::vector< Short_vehicleanonymous_namespace{optimize_driver.cpp}::subdivide_processing (PickDeliveryOrders_t *shipments_arr, size_t total_shipments, Vehicle_t *vehicles_arr, size_t total_vehicles, const vrprouting::problem::Matrix &time_matrix, int max_cycles, int64_t execution_date, bool subdivide_by_vehicle, std::ostringstream &log)
 Executes an optimization by subdivision of data. More...
 
void anonymous_namespace{optimize_driver.cpp}::update_stops (std::vector< Short_vehicle > &the_stops, const std::vector< Short_vehicle > new_values)
 Update the vehicle stops to the new values. More...
 

Function Documentation

◆ do_optimize()

void do_optimize ( PickDeliveryOrders_t shipments_arr,
size_t  total_shipments,
Vehicle_t vehicles_arr,
size_t  total_vehicles,
Matrix_cell_t matrix_cells_arr,
size_t  total_cells,
Time_multipliers_t multipliers_arr,
size_t  total_multipliers,
double  factor,
int  max_cycles,
int64_t  execution_date,
bool  check_triangle_inequality,
bool  subdivide,
bool  subdivide_by_vehicle,
Short_vehicle_rt **  return_tuples,
size_t *  return_count,
char **  log_msg,
char **  notice_msg,
char **  err_msg 
)
Parameters
[in]shipments_arrA C Array of pickup and dropoff shipments
[in]total_shipmentssize of the shipments_arr
[in]vehicles_arrA C Array of vehicles
[in]total_vehiclessize of the vehicles_arr
[in]matrix_cells_arrA C Array of the (time) matrix cells
[in]total_cellssize of the matrix_cells_arr
[in]multipliers_arrA C Array of the multipliers
[in]total_multiplierssize of the multipliers_arr
[in]optimizeflag to control optimization
[in]factorA global multiplier for the (time) matrix cells
[in]max_cyclesnumber of cycles to perform during the optimization phase
[in]stop_on_all_servedIndicator to stop optimization when all shipments are served
[in]execution_dateValue used for not moving shipments that are before this date
[out]return_tuplesC array of contents to be returned to postgres
[out]return_countnumber of tuples returned
[out]log_msgspecial log message pointer
[out]notice_msgspecial message pointer to be returned as NOTICE
[out]err_msgspecial message pointer to be returned as ERROR
Returns
void
Precondition
The messages: log_msg, notice_msg, err_msg must be empty (=nullptr)
The C arrays: shipments_arr, vehicles_arr, matrix_cells_arr must not be empty
The C array: return_tuples must be empty
Only matrix cells (i, i) can be missing and are considered as 0 (time units)
Postcondition
The C arrays: shipments_arr, vehicles_arr, matrix_cells_arr Do not change
The C array: return_tuples contains the result for the problem given
The return_tuples array size is return_count
err_msg is empty if no throw from the process is catched
log_msg contains some logging
notice_msg is empty
dot_inline_dotgraph_3.png

Definition at line 350 of file optimize_driver.cpp.

370  {
371  std::ostringstream log;
372  std::ostringstream notice;
373  std::ostringstream err;
374  try {
375  /*
376  * verify preconditions
377  */
378  pgassert(!(*log_msg));
379  pgassert(!(*notice_msg));
380  pgassert(!(*err_msg));
381  pgassert(total_shipments);
382  pgassert(total_vehicles);
383  pgassert(total_cells);
384  pgassert(*return_count == 0);
385  pgassert(!(*return_tuples));
386 
387  *return_tuples = nullptr;
388  *return_count = 0;
389 
390  Identifiers<Id> node_ids;
391  Identifiers<Id> shipments_in_stops;
392 
393  /*
394  * Remove vehicles not going to be optimized and sort remaining vehicles
395  * 1. sort by id
396  * 2. remove duplicates
397  * - data comes from query that could possibly give a duplicate
398  * 3. remove vehicles that closes(end) before the execution time
399  */
400  std::sort(vehicles_arr, vehicles_arr + total_vehicles,
401  [](const Vehicle_t& lhs, const Vehicle_t& rhs){return lhs.id < rhs.id;});
402 
403  total_vehicles = static_cast<size_t>(std::distance(vehicles_arr,
404  std::unique(vehicles_arr, vehicles_arr + total_vehicles,
405  [&](const Vehicle_t& lhs, const Vehicle_t& rhs){return lhs.id == rhs.id;})));
406 
407  total_vehicles = static_cast<size_t>(std::distance(vehicles_arr,
408  std::remove_if(vehicles_arr, vehicles_arr + total_vehicles,
409  [&](const Vehicle_t& v){return v.end_close_t < execution_date;})));
410 
411  /*
412  * Remove shipments not involved in optimization
413  * 1. get the shipments on the stops of the vehicles
414  * - getting the node_ids in the same cycle
415  * 2. Remove duplicates
416  * 2. Remove shipments not on the stops
417  */
418  for (size_t i = 0; i < total_vehicles; ++i) {
419  node_ids += vehicles_arr[i].start_node_id;
420  node_ids += vehicles_arr[i].end_node_id;
421  for (size_t j = 0; j < vehicles_arr[i].stops_size; ++j) {
422  shipments_in_stops += vehicles_arr[i].stops[j];
423  }
424  }
425 
426  std::sort(shipments_arr, shipments_arr + total_shipments,
427  [](const PickDeliveryOrders_t& lhs, const PickDeliveryOrders_t& rhs){return lhs.id < rhs.id;});
428 
429  total_shipments = static_cast<size_t>(std::distance(shipments_arr,
430  std::unique(shipments_arr, shipments_arr + total_shipments,
431  [&](const PickDeliveryOrders_t& lhs, const PickDeliveryOrders_t& rhs){return lhs.id == rhs.id;})));
432 
433  total_shipments = static_cast<size_t>(std::distance(shipments_arr,
434  std::remove_if(shipments_arr, shipments_arr + total_shipments,
435  [&](const PickDeliveryOrders_t& s){return !shipments_in_stops.has(s.id);})));
436 
437  /*
438  * Verify shipments complete data
439  */
440  if (shipments_in_stops.size() != total_shipments) {
441  for (size_t i = 0; i < total_shipments; ++i) {
442  shipments_in_stops -= shipments_arr[i].id;
443  }
444  std::ostringstream hint;
445  err << "Missing shipments for processing ";
446  hint << "Shipments missing: " << shipments_in_stops << log.str();
447  *log_msg = pgr_msg(hint.str());
448  *err_msg = pgr_msg(err.str());
449  return;
450  }
451 
452  /*
453  * Finish getting the node ids involved on the process
454  */
455  for (size_t i = 0; i < total_shipments; ++i) {
456  node_ids += shipments_arr[i].pick_node_id;
457  node_ids += shipments_arr[i].deliver_node_id;
458  }
459 
460  /*
461  * Dealing with time matrix:
462  * - Create the unique time matrix to be used for all optimizations
463  * - Verify matrix triangle inequality
464  * - Verify matrix cells preconditions
465  */
466  vrprouting::problem::Matrix time_matrix(
467  matrix_cells_arr, total_cells,
468  multipliers_arr, total_multipliers,
469  node_ids, static_cast<Multiplier>(factor));
470 
471  if (check_triangle_inequality && !time_matrix.obeys_triangle_inequality()) {
472  log << "\nFixing Matrix that does not obey triangle inequality "
473  << time_matrix.fix_triangle_inequality() << " cycles used";
474 
475  if (!time_matrix.obeys_triangle_inequality()) {
476  log << "\nMatrix Still does not obey triangle inequality ";
477  }
478  }
479 
480  if (!time_matrix.has_no_infinity()) {
481  err << "\nAn Infinity value was found on the Matrix";
482  *err_msg = pgr_msg(err.str());
483  *log_msg = pgr_msg(log.str());
484  return;
485  }
486 
487  /*
488  * get the solution
489  */
490  auto solution = subdivide?
492  shipments_arr, total_shipments,
493  vehicles_arr, total_vehicles,
494  time_matrix,
495  max_cycles, execution_date,
496  subdivide_by_vehicle,
497  log) :
499  shipments_arr, total_shipments,
500  vehicles_arr, total_vehicles, {},
501  time_matrix,
502  max_cycles, execution_date);
503 
504  /*
505  * Prepare results
506  */
507  if (!solution.empty()) {
508  (*return_tuples) = pgr_alloc(total_shipments * 2, (*return_tuples));
509 
510  size_t seq = 0;
511  for (const auto &row : solution) {
512  for (const auto &o_id : row.stops) {
513  (*return_tuples)[seq].vehicle_id = row.id;
514  (*return_tuples)[seq].order_id = o_id;
515  ++seq;
516  }
517  }
518  }
519 
520  (*return_count) = total_shipments * 2;
521 
522  pgassert(*err_msg == nullptr);
523  *log_msg = log.str().empty()?
524  nullptr :
525  pgr_msg(log.str());
526  *notice_msg = notice.str().empty()?
527  nullptr :
528  pgr_msg(notice.str());
529  } catch (AssertFailedException &except) {
530  err << except.what() << log.str();
531  *err_msg = pgr_msg(err.str());
532  } catch (std::exception& except) {
533  err << except.what() << log.str();
534  *err_msg = pgr_msg(err.str());
535  } catch (const std::pair<std::string, std::string>& ex) {
536  err << ex.first;
537  log.str("");
538  log.clear();
539  log << ex.second;
540  *err_msg = pgr_msg(err.str().c_str());
541  *log_msg = pgr_msg(log.str().c_str());
542  } catch(...) {
543  err << "Caught unknown exception!" << log.str();
544  *err_msg = pgr_msg(err.str());
545  }
546 }

References PickDeliveryOrders_t::deliver_node_id, Vehicle_t::end_close_t, Vehicle_t::end_node_id, vrprouting::base::Base_Matrix::fix_triangle_inequality(), Identifiers< T >::has(), vrprouting::base::Base_Matrix::has_no_infinity(), Vehicle_t::id, PickDeliveryOrders_t::id, vrprouting::base::Base_Matrix::obeys_triangle_inequality(), anonymous_namespace{optimize_driver.cpp}::one_processing(), pgassert, pgr_alloc(), pgr_msg(), PickDeliveryOrders_t::pick_node_id, Identifiers< T >::size(), Vehicle_t::start_node_id, Vehicle_t::stops, Vehicle_t::stops_size, anonymous_namespace{optimize_driver.cpp}::subdivide_processing(), and AssertFailedException::what().

Referenced by process().

PickDeliveryOrders_t::deliver_node_id
Id deliver_node_id
Deliver y coordinate: used in stand alone program for benchmarks.
Definition: pickDeliveryOrders_t.h:72
pgr_alloc
T * pgr_alloc(std::size_t size, T *ptr)
allocates memory
Definition: pgr_alloc.hpp:66
Vehicle_t::start_node_id
Id start_node_id
Stops size.
Definition: vehicle_t.h:58
Vehicle_t::stops
Id * stops
Number of vehicles with same description.
Definition: vehicle_t.h:55
Vehicle_t::end_node_id
Id end_node_id
Definition: vehicle_t.h:65
pgr_msg
char * pgr_msg(const std::string &msg)
Definition: pgr_alloc.cpp:33
AssertFailedException::what
virtual const char * what() const
Definition: pgr_assert.cpp:67
PickDeliveryOrders_t
order's attributes
Definition: pickDeliveryOrders_t.h:56
anonymous_namespace{optimize_driver.cpp}::one_processing
std::vector< Short_vehicle > one_processing(PickDeliveryOrders_t *shipments_arr, size_t total_shipments, Vehicle_t *vehicles_arr, size_t total_vehicles, std::vector< Short_vehicle > new_stops, const vrprouting::problem::Matrix &time_matrix, int max_cycles, int64_t execution_date)
Executes an optimization with the input data.
Definition: optimize_driver.cpp:69
Vehicle_t
vehicles's attributes
Definition: vehicle_t.h:50
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:95
anonymous_namespace{optimize_driver.cpp}::subdivide_processing
std::vector< Short_vehicle > subdivide_processing(PickDeliveryOrders_t *shipments_arr, size_t total_shipments, Vehicle_t *vehicles_arr, size_t total_vehicles, const vrprouting::problem::Matrix &time_matrix, int max_cycles, int64_t execution_date, bool subdivide_by_vehicle, std::ostringstream &log)
Executes an optimization by subdivision of data.
Definition: optimize_driver.cpp:213
Identifiers::size
size_t size() const
Definition: identifiers.hpp:77
vrprouting::problem::Matrix
Definition: matrix.h:46
PickDeliveryOrders_t::id
Id id
Definition: pickDeliveryOrders_t.h:59
PickDeliveryOrders_t::pick_node_id
Id pick_node_id
Pick y coordinate: used in stand alone program for benchmarks.
Definition: pickDeliveryOrders_t.h:64
Identifiers::has
bool has(const T other) const
true ids() has element
Definition: identifiers.hpp:100
Vehicle_t::end_close_t
TTimestamp end_close_t
End open time.
Definition: vehicle_t.h:67
Multiplier
double Multiplier
Definition: typedefs.h:77
Vehicle_t::stops_size
size_t stops_size
Stops.
Definition: vehicle_t.h:56
Vehicle_t::id
Id id
Definition: vehicle_t.h:51
Identifiers
Definition: identifiers.hpp:51
AssertFailedException
Extends std::exception and is the exception that we throw if an assert fails.
Definition: pgr_assert.h:140