vrpRouting  0.3
pickDeliver/pickDeliver.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: pickDeliver.c
3 
4 Copyright (c) 2021 pgRouting developers
6 
7 Developer:
8 Copyright (c) 2021 Celia Virginia Vergara Castillo
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 <stdbool.h>
31 #include <utils/date.h> // NOLINT [build/include_order]
32 #include "c_common/debug_macro.h"
33 #include "c_common/e_report.h"
34 #include "c_common/time_msg.h"
35 #include "c_common/orders_input.h"
40 #include "c_types/solution_rt.h"
43 
44 PGDLLEXPORT Datum _vrp_pickdeliver(PG_FUNCTION_ARGS);
46 PGDLLEXPORT Datum _vrp_pickdeliverraw(PG_FUNCTION_ARGS);
48 
49 
50 static
51 void
53  char* pd_orders_sql,
54  char* vehicles_sql,
55  char* matrix_sql,
56  char* multipliers_sql,
57 
58  bool optimize,
59  double factor,
60  int max_cycles,
61  bool stop_on_all_served,
62  int64_t execution_date,
63 
64  bool use_timestamps,
65 
66  Solution_rt **result_tuples,
67  size_t *result_count) {
68  /*
69  * Adjusting timestamp data to timezone UTC
70  */
71  if (use_timestamps) {
72  execution_date = timestamp_without_timezone(execution_date);
73  }
74 
75  PGR_DBG("execution_date: %ld ", execution_date);
76 
78  if (factor <= 0) {
79  ereport(ERROR,
80  (errcode(ERRCODE_INTERNAL_ERROR),
81  errmsg("Illegal value in parameter: factor"),
82  errhint("Value found: %f <= 0", factor)));
83  }
85 
86  if (max_cycles < 0) {
87  ereport(ERROR,
88  (errcode(ERRCODE_INTERNAL_ERROR),
89  errmsg("Illegal value in parameter: max_cycles"),
90  errhint("Value found: %d <= 0", max_cycles)));
91  }
92 
94 
95  PickDeliveryOrders_t *pd_orders_arr = NULL;
96  size_t total_pd_orders = 0;
97  if (use_timestamps) {
98  get_shipments(pd_orders_sql, &pd_orders_arr, &total_pd_orders);
99  } else {
100  get_shipments_raw(pd_orders_sql, &pd_orders_arr, &total_pd_orders);
101  }
102 
103  if (total_pd_orders == 0) {
104  (*result_count) = 0;
105  (*result_tuples) = NULL;
106 
107  /* freeing memory before return */
108  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
109 
110  pgr_SPI_finish();
111  return;
112  }
113 
114  Vehicle_t *vehicles_arr = NULL;
115  size_t total_vehicles = 0;
116  if (use_timestamps) {
117  get_vehicles(vehicles_sql, &vehicles_arr, &total_vehicles, true);
118  } else {
119  get_vehicles_raw(vehicles_sql, &vehicles_arr, &total_vehicles, true);
120  }
121 
122  if (total_vehicles == 0) {
123  (*result_count) = 0;
124  (*result_tuples) = NULL;
125 
126  /* freeing memory before return */
127  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
128  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
129 
130  ereport(WARNING,
131  (errcode(ERRCODE_INTERNAL_ERROR),
132  errmsg("No vehicles found")));
133 
134  pgr_SPI_finish();
135  return;
136  }
137 
138  Time_multipliers_t *multipliers_arr = NULL;
139  size_t total_multipliers_arr = 0;
140  if (use_timestamps) {
141  PGR_DBG("get_timeMultipliers");
142  get_timeMultipliers(multipliers_sql, &multipliers_arr, &total_multipliers_arr);
143  } else {
144  PGR_DBG("get_timeMultipliers_raw");
145  get_timeMultipliers_raw(multipliers_sql, &multipliers_arr, &total_multipliers_arr);
146  }
147 
148  if (total_multipliers_arr == 0) {
149  ereport(WARNING,
150  (errcode(ERRCODE_INTERNAL_ERROR),
151  errmsg("No matrix found")));
152  (*result_count) = 0;
153  (*result_tuples) = NULL;
154 
155  /* freeing memory before return */
156  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
157  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
158  if (multipliers_arr) {pfree(multipliers_arr); multipliers_arr = NULL;}
159 
160  pgr_SPI_finish();
161  return;
162  }
163 
164  Matrix_cell_t *matrix_cells_arr = NULL;
165  size_t total_cells = 0;
166  if (use_timestamps) {
167  get_matrixRows(matrix_sql, &matrix_cells_arr, &total_cells);
168  } else {
169  get_matrixRows_plain(matrix_sql, &matrix_cells_arr, &total_cells);
170  }
171 
172  if (total_cells == 0) {
173  (*result_count) = 0;
174  (*result_tuples) = NULL;
175 
176  /* freeing memory before return */
177  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
178  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
179  if (multipliers_arr) {pfree(multipliers_arr); multipliers_arr = NULL;}
180  if (matrix_cells_arr) {pfree(matrix_cells_arr); matrix_cells_arr = NULL;}
181 
182  ereport(WARNING,
183  (errcode(ERRCODE_INTERNAL_ERROR),
184  errmsg("No matrix found")));
185  pgr_SPI_finish();
186  return;
187  }
188 
189  PGR_DBG("Total %ld orders in query:", total_pd_orders);
190  PGR_DBG("Total %ld vehicles in query:", total_vehicles);
191  PGR_DBG("Total %ld matrix cells in query:", total_cells);
192  PGR_DBG("Total %ld time dependant multipliers:", total_multipliers_arr);
193 
194  clock_t start_t = clock();
195  char *log_msg = NULL;
196  char *notice_msg = NULL;
197  char *err_msg = NULL;
198 
200  pd_orders_arr, total_pd_orders,
201  vehicles_arr, total_vehicles,
202  matrix_cells_arr, total_cells,
203  multipliers_arr, total_multipliers_arr,
204 
205  optimize,
206  factor,
207  max_cycles,
208  stop_on_all_served,
209 
210  execution_date,
211 
212  result_tuples,
213  result_count,
214 
215  &log_msg,
216  &notice_msg,
217  &err_msg);
218 
219  time_msg("pgr_pickDeliver", start_t, clock());
220 
221  if (err_msg && (*result_tuples)) {
222  pfree(*result_tuples);
223  (*result_count) = 0;
224  (*result_tuples) = NULL;
225  }
226  pgr_global_report(log_msg, notice_msg, err_msg);
227 
228  /* freeing memory before return */
229  if (log_msg) {pfree(log_msg); log_msg = NULL;}
230  if (notice_msg) {pfree(notice_msg); notice_msg = NULL;}
231  if (err_msg) {pfree(err_msg); err_msg = NULL;}
232  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
233  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
234  if (multipliers_arr) {pfree(multipliers_arr); multipliers_arr = NULL;}
235  if (matrix_cells_arr) {pfree(matrix_cells_arr); matrix_cells_arr = NULL;}
236 
237  pgr_SPI_finish();
238 }
239 
240 
241 
245 PGDLLEXPORT Datum
246 _vrp_pickdeliver(PG_FUNCTION_ARGS) {
247  FuncCallContext *funcctx;
248  TupleDesc tuple_desc;
249 
250  /**************************************************************************/
251  Solution_rt *result_tuples = 0;
252  size_t result_count = 0;
253  /**************************************************************************/
254 
255  if (SRF_IS_FIRSTCALL()) {
256  MemoryContext oldcontext;
257  funcctx = SRF_FIRSTCALL_INIT();
258  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
259 
260  process(
261  text_to_cstring(PG_GETARG_TEXT_P(0)),
262  text_to_cstring(PG_GETARG_TEXT_P(1)),
263  text_to_cstring(PG_GETARG_TEXT_P(2)),
264  text_to_cstring(PG_GETARG_TEXT_P(3)),
265 
266  PG_GETARG_BOOL(4),
267  PG_GETARG_FLOAT8(5),
268  PG_GETARG_INT32(6),
269  PG_GETARG_BOOL(7),
270  PG_GETARG_TIMEADT(8),
271  true,
272 
273  &result_tuples,
274  &result_count);
275 
276  /*********************************************************************/
277 
278  funcctx->max_calls = result_count;
279  funcctx->user_fctx = result_tuples;
280  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
281  != TYPEFUNC_COMPOSITE) {
282  ereport(ERROR,
283  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
284  errmsg("function returning record called in context "
285  "that cannot accept type record")));
286  }
287 
288  funcctx->tuple_desc = tuple_desc;
289  MemoryContextSwitchTo(oldcontext);
290  }
291 
292  funcctx = SRF_PERCALL_SETUP();
293  tuple_desc = funcctx->tuple_desc;
294  result_tuples = (Solution_rt*) funcctx->user_fctx;
295 
296  if (funcctx->call_cntr < funcctx->max_calls) {
297  HeapTuple tuple;
298  Datum result;
299  Datum *values;
300  bool* nulls;
301  size_t call_cntr = funcctx->call_cntr;
302 
303  size_t numb = 16;
304  values = palloc(numb * sizeof(Datum));
305  nulls = palloc(numb * sizeof(bool));
306 
307  size_t i;
308  for (i = 0; i < numb; ++i) {
309  nulls[i] = false;
310  }
311 
312 
313  values[0] = Int32GetDatum(funcctx->call_cntr + 1);
314  values[1] = Int32GetDatum(result_tuples[call_cntr].vehicle_seq);
315  values[2] = Int64GetDatum(result_tuples[call_cntr].vehicle_id);
316  values[3] = Int32GetDatum(result_tuples[call_cntr].stop_seq);
317  values[4] = Int32GetDatum(result_tuples[call_cntr].stop_type + 1);
318  values[5] = Int64GetDatum(result_tuples[call_cntr].stop_id);
319  values[6] = Int64GetDatum(result_tuples[call_cntr].order_id);
320  values[7] = Int64GetDatum(result_tuples[call_cntr].cargo);
321  values[8] = Int64GetDatum(result_tuples[call_cntr].travelTime);
322  values[9] = Int64GetDatum(result_tuples[call_cntr].arrivalTime);
323  values[10] = Int64GetDatum(result_tuples[call_cntr].waitDuration);
324  values[11] = Int64GetDatum(result_tuples[call_cntr].operationTime);
325  values[12] = Int64GetDatum(result_tuples[call_cntr].serviceDuration);
326  values[13] = Int64GetDatum(result_tuples[call_cntr].departureTime);
327  values[14] = Int32GetDatum(result_tuples[call_cntr].cvTot);
328  values[15] = Int32GetDatum(result_tuples[call_cntr].twvTot);
329 
330  /*********************************************************************/
331 
332  tuple = heap_form_tuple(tuple_desc, values, nulls);
333  result = HeapTupleGetDatum(tuple);
334 
335  pfree(values); values = NULL;
336  pfree(nulls); nulls = NULL;
337 
338  SRF_RETURN_NEXT(funcctx, result);
339  } else {
340  if (result_tuples) {pfree(result_tuples); result_tuples = NULL;}
341  funcctx->user_fctx = NULL;
342  SRF_RETURN_DONE(funcctx);
343  }
344 }
345 /******************************************************************************/
346 
347 
351 PGDLLEXPORT Datum
352 _vrp_pickdeliverraw(PG_FUNCTION_ARGS) {
353  FuncCallContext *funcctx;
354  TupleDesc tuple_desc;
355 
356  /**************************************************************************/
357  Solution_rt *result_tuples = 0;
358  size_t result_count = 0;
359  /**************************************************************************/
360 
361  if (SRF_IS_FIRSTCALL()) {
362  MemoryContext oldcontext;
363  funcctx = SRF_FIRSTCALL_INIT();
364  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
365 
366  process(
367  text_to_cstring(PG_GETARG_TEXT_P(0)),
368  text_to_cstring(PG_GETARG_TEXT_P(1)),
369  text_to_cstring(PG_GETARG_TEXT_P(2)),
370  text_to_cstring(PG_GETARG_TEXT_P(3)),
371 
372  PG_GETARG_BOOL(4),
373  PG_GETARG_FLOAT8(5),
374  PG_GETARG_INT32(6),
375  PG_GETARG_BOOL(7),
376  PG_GETARG_INT64(8),
377  false,
378 
379  &result_tuples,
380  &result_count);
381 
382  /*********************************************************************/
383 
384  funcctx->max_calls = result_count;
385  funcctx->user_fctx = result_tuples;
386  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
387  != TYPEFUNC_COMPOSITE) {
388  ereport(ERROR,
389  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
390  errmsg("function returning record called in context "
391  "that cannot accept type record")));
392  }
393 
394  funcctx->tuple_desc = tuple_desc;
395  MemoryContextSwitchTo(oldcontext);
396  }
397 
398  funcctx = SRF_PERCALL_SETUP();
399  tuple_desc = funcctx->tuple_desc;
400  result_tuples = (Solution_rt*) funcctx->user_fctx;
401 
402  if (funcctx->call_cntr < funcctx->max_calls) {
403  HeapTuple tuple;
404  Datum result;
405  Datum *values;
406  bool* nulls;
407  size_t call_cntr = funcctx->call_cntr;
408 
409  size_t numb = 16;
410  values = palloc(numb * sizeof(Datum));
411  nulls = palloc(numb * sizeof(bool));
412 
413  size_t i;
414  for (i = 0; i < numb; ++i) {
415  nulls[i] = false;
416  }
417 
418 
419  values[0] = Int32GetDatum(funcctx->call_cntr + 1);
420  values[1] = Int32GetDatum(result_tuples[call_cntr].vehicle_seq);
421  values[2] = Int64GetDatum(result_tuples[call_cntr].vehicle_id);
422  values[3] = Int32GetDatum(result_tuples[call_cntr].stop_seq);
423  values[4] = Int32GetDatum(result_tuples[call_cntr].stop_type + 1);
424  values[5] = Int64GetDatum(result_tuples[call_cntr].stop_id);
425  values[6] = Int64GetDatum(result_tuples[call_cntr].order_id);
426  values[7] = Int64GetDatum(result_tuples[call_cntr].cargo);
427  values[8] = Int64GetDatum(result_tuples[call_cntr].travelTime);
428  values[9] = Int64GetDatum(result_tuples[call_cntr].arrivalTime);
429  values[10] = Int64GetDatum(result_tuples[call_cntr].waitDuration);
430  values[11] = Int64GetDatum(result_tuples[call_cntr].operationTime);
431  values[12] = Int64GetDatum(result_tuples[call_cntr].serviceDuration);
432  values[13] = Int64GetDatum(result_tuples[call_cntr].departureTime);
433  values[14] = Int32GetDatum(result_tuples[call_cntr].cvTot);
434  values[15] = Int32GetDatum(result_tuples[call_cntr].twvTot);
435 
436  /*********************************************************************/
437 
438  tuple = heap_form_tuple(tuple_desc, values, nulls);
439  result = HeapTupleGetDatum(tuple);
440 
441  pfree(values); values = NULL;
442  pfree(nulls); nulls = NULL;
443 
444  SRF_RETURN_NEXT(funcctx, result);
445  } else {
446  if (result_tuples) {pfree(result_tuples); result_tuples = NULL;}
447  funcctx->user_fctx = NULL;
448  SRF_RETURN_DONE(funcctx);
449  }
450 }
time_msg.h
pickDeliveryOrders_t.h
PG_FUNCTION_INFO_V1
PG_FUNCTION_INFO_V1(_vrp_pickdeliver)
postgres_connection.h
get_matrixRows
void get_matrixRows(char *sql, Matrix_cell_t **rows, size_t *total_rows)
Get the travel time matrix.
Definition: matrixRows_input.c:176
PickDeliveryOrders_t
order's attributes
Definition: pickDeliveryOrders_t.h:56
pgr_SPI_connect
void pgr_SPI_connect(void)
Definition: postgres_connection.c:79
get_matrixRows_plain
void get_matrixRows_plain(char *sql, Matrix_cell_t **rows, size_t *total_rows)
Get the travel time matrix with numerical types.
Definition: matrixRows_input.c:203
Time_multipliers_t
Time Dependant Multipliers.
Definition: time_multipliers_t.h:46
_vrp_pickdeliver
PGDLLEXPORT Datum _vrp_pickdeliver(PG_FUNCTION_ARGS)
the timestamp version of the function
Definition: pickDeliver/pickDeliver.c:246
pgr_SPI_finish
void pgr_SPI_finish(void)
Definition: postgres_connection.c:71
e_report.h
matrixRows_input.h
Vehicle_t
vehicles's attributes
Definition: vehicle_t.h:50
orders_input.h
vehicles_input.h
get_timeMultipliers
void get_timeMultipliers(char *sql, Time_multipliers_t **rows, size_t *total_rows)
Get the time multipliers using interval.
Definition: time_multipliers_input.c:149
debug_macro.h
get_vehicles_raw
void get_vehicles_raw(char *sql, Vehicle_t **rows, size_t *total_rows, bool with_stops)
Reads the vehicles information.
Definition: vehicles_input.c:522
get_shipments
void get_shipments(char *sql, PickDeliveryOrders_t **rows, size_t *total_rows)
Reads the pick-Deliver shipments for timestams and intervals.
Definition: orders_input.c:331
pickDeliver_driver.h
timestamp_without_timezone
TTimestamp timestamp_without_timezone(TTimestamp timestamp)
Steps: 1) Similar to: https://doxygen.postgresql.org/backend_2utils_2adt_2timestamp_8c....
Definition: get_check_data.c:847
PGR_DBG
#define PGR_DBG(...)
Definition: debug_macro.h:34
Solution_rt
Solution schedule when twv & cw are hard restrictions.
Definition: solution_rt.h:56
process
static void process(char *pd_orders_sql, char *vehicles_sql, char *matrix_sql, char *multipliers_sql, bool optimize, double factor, int max_cycles, bool stop_on_all_served, int64_t execution_date, bool use_timestamps, Solution_rt **result_tuples, size_t *result_count)
Definition: pickDeliver/pickDeliver.c:52
do_pickDeliver
void do_pickDeliver(PickDeliveryOrders_t *customers_arr, size_t total_customers, 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, bool optimize, double factor, int max_cycles, bool stop_on_all_served, int64_t execution_date, Solution_rt **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)
Definition: pickDeliver/pickDeliver_driver.cpp:108
if
if(DOXYGEN_FOUND) configure_file($
Definition: doxygen/CMakeLists.txt:13
_vrp_pickdeliverraw
PGDLLEXPORT Datum _vrp_pickdeliverraw(PG_FUNCTION_ARGS)
the plain version of the function
Definition: pickDeliver/pickDeliver.c:352
Matrix_cell_t
traveling costs
Definition: matrix_cell_t.h:41
get_vehicles
void get_vehicles(char *sql, Vehicle_t **rows, size_t *total_rows, bool with_stops)
Reads the vehicles information.
Definition: vehicles_input.c:469
time_msg
void time_msg(char *msg, clock_t start_t, clock_t end_t)
Definition: time_msg.c:32
solution_rt.h
time_multipliers_input.h
get_timeMultipliers_raw
void get_timeMultipliers_raw(char *sql, Time_multipliers_t **rows, size_t *total_rows)
Get the time multipliers using bigint.
Definition: time_multipliers_input.c:175
get_check_data.h
pgr_global_report
void pgr_global_report(char *log, char *notice, char *err)
notice & error
Definition: e_report.c:30
get_shipments_raw
void get_shipments_raw(char *sql, PickDeliveryOrders_t **rows, size_t *total_rows)
Reads the pick-Deliver shipments for raw data.
Definition: orders_input.c:376