vrpRouting  0.3
optimize.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: optimize.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 "c_common/debug_macro.h"
32 #include "c_common/e_report.h"
33 #include "c_common/time_msg.h"
34 #include "c_common/orders_input.h"
41 
42 PGDLLEXPORT Datum
43 _vrp_optimize(PG_FUNCTION_ARGS);
45 
46 
47 static
48 void
50  char* pd_orders_sql,
51  char* vehicles_sql,
52  char* matrix_sql,
53  char* multipliers_sql,
54 
55  double factor,
56  int max_cycles,
57  int64_t execution_date,
58 
59  bool check_triangle_inequality,
60  int subdivision_kind,
61  bool use_timestamps,
62 
63  Short_vehicle_rt **result_tuples,
64  size_t *result_count) {
66  if (factor <= 0) {
67  ereport(ERROR,
68  (errcode(ERRCODE_INTERNAL_ERROR),
69  errmsg("Illegal value in parameter: factor"),
70  errhint("Value found: %f <= 0", factor)));
71  }
72 
74  if (max_cycles < 0) {
75  ereport(ERROR,
76  (errcode(ERRCODE_INTERNAL_ERROR),
77  errmsg("Illegal value in parameter: max_cycles"),
78  errhint("Value found: %d <= 0", max_cycles)));
79  }
80 
82  if (subdivision_kind < 0 || subdivision_kind > 2) {
83  ereport(ERROR,
84  (errcode(ERRCODE_INTERNAL_ERROR),
85  errmsg("Illegal value in parameter: subdivision_kind"),
86  errhint("Value found: %d", max_cycles)));
87  }
88 
90 
91  PickDeliveryOrders_t *pd_orders_arr = NULL;
92  size_t total_pd_orders = 0;
93  if (use_timestamps) {
94  get_shipments(pd_orders_sql, &pd_orders_arr, &total_pd_orders);
95  } else {
96  get_shipments_raw(pd_orders_sql, &pd_orders_arr, &total_pd_orders);
97  }
98 
99  if (total_pd_orders == 0) {
100  (*result_count) = 0;
101  (*result_tuples) = NULL;
102 
103  /* freeing memory before return */
104  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
105 
106  pgr_SPI_finish();
107  return;
108  }
109 
110  Vehicle_t *vehicles_arr = NULL;
111  size_t total_vehicles = 0;
112  if (use_timestamps) {
113  get_vehicles(vehicles_sql, &vehicles_arr, &total_vehicles, true);
114  } else {
115  get_vehicles_raw(vehicles_sql, &vehicles_arr, &total_vehicles, true);
116  }
117 
118  if (total_vehicles == 0) {
119  (*result_count) = 0;
120  (*result_tuples) = NULL;
121 
122  /* freeing memory before return */
123  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
124  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
125 
126  ereport(WARNING,
127  (errcode(ERRCODE_INTERNAL_ERROR),
128  errmsg("No vehicles found")));
129 
130  pgr_SPI_finish();
131  return;
132  }
133 
134  Time_multipliers_t *multipliers_arr = NULL;
135  size_t total_multipliers_arr = 0;
136  if (use_timestamps) {
137  get_timeMultipliers(multipliers_sql, &multipliers_arr, &total_multipliers_arr);
138  } else {
139  get_timeMultipliers_raw(multipliers_sql, &multipliers_arr, &total_multipliers_arr);
140  }
141 
142  if (total_multipliers_arr == 0) {
143  ereport(WARNING,
144  (errcode(ERRCODE_INTERNAL_ERROR),
145  errmsg("No matrix found")));
146  (*result_count) = 0;
147  (*result_tuples) = NULL;
148 
149  /* freeing memory before return */
150  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
151  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
152  if (multipliers_arr) {pfree(multipliers_arr); multipliers_arr = NULL;}
153 
154  pgr_SPI_finish();
155  return;
156  }
157 
158  Matrix_cell_t *matrix_cells_arr = NULL;
159  size_t total_cells = 0;
160  if (use_timestamps) {
161  get_matrixRows(matrix_sql, &matrix_cells_arr, &total_cells);
162  } else {
163  get_matrixRows_plain(matrix_sql, &matrix_cells_arr, &total_cells);
164  }
165 
166  if (total_cells == 0) {
167  (*result_count) = 0;
168  (*result_tuples) = NULL;
169 
170  /* freeing memory before return */
171  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
172  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
173  if (multipliers_arr) {pfree(multipliers_arr); multipliers_arr = NULL;}
174  if (matrix_cells_arr) {pfree(matrix_cells_arr); matrix_cells_arr = NULL;}
175 
176  ereport(WARNING,
177  (errcode(ERRCODE_INTERNAL_ERROR),
178  errmsg("No matrix found")));
179  pgr_SPI_finish();
180  return;
181  }
182 
183  PGR_DBG("Total %ld orders in query:", total_pd_orders);
184  PGR_DBG("Total %ld vehicles in query:", total_vehicles);
185  PGR_DBG("Total %ld matrix cells in query:", total_cells);
186  PGR_DBG("Total %ld time dependant multipliers:", total_multipliers_arr);
187 
188  clock_t start_t = clock();
189  char *log_msg = NULL;
190  char *notice_msg = NULL;
191  char *err_msg = NULL;
192 
193  do_optimize(
194  pd_orders_arr, total_pd_orders,
195  vehicles_arr, total_vehicles,
196  matrix_cells_arr, total_cells,
197  multipliers_arr, total_multipliers_arr,
198 
199  factor,
200  max_cycles,
201  execution_date,
202 
203  check_triangle_inequality,
204  subdivision_kind != 0,
205  subdivision_kind == 1,
206 
207  result_tuples,
208  result_count,
209 
210  &log_msg,
211  &notice_msg,
212  &err_msg);
213 
214  time_msg("pgr_pickDeliver", start_t, clock());
215 
216  if (err_msg && (*result_tuples)) {
217  pfree(*result_tuples);
218  (*result_count) = 0;
219  (*result_tuples) = NULL;
220  }
221  pgr_global_report(log_msg, notice_msg, err_msg);
222 
223  /* freeing memory before return */
224  if (log_msg) {pfree(log_msg); log_msg = NULL;}
225  if (notice_msg) {pfree(notice_msg); notice_msg = NULL;}
226  if (err_msg) {pfree(err_msg); err_msg = NULL;}
227  if (pd_orders_arr) {pfree(pd_orders_arr); pd_orders_arr = NULL;}
228  if (vehicles_arr) {pfree(vehicles_arr); vehicles_arr = NULL;}
229  if (multipliers_arr) {pfree(multipliers_arr); multipliers_arr = NULL;}
230  if (matrix_cells_arr) {pfree(matrix_cells_arr); matrix_cells_arr = NULL;}
231 
232  pgr_SPI_finish();
233 }
234 
235 
236 
237 /******************************************************************************/
238 
239 
240 PGDLLEXPORT Datum
241 _vrp_optimize(PG_FUNCTION_ARGS) {
242  FuncCallContext *funcctx;
243  TupleDesc tuple_desc;
244 
245  /**************************************************************************/
246  Short_vehicle_rt *result_tuples = 0;
247  size_t result_count = 0;
248  /**************************************************************************/
249 
250  if (SRF_IS_FIRSTCALL()) {
251  MemoryContext oldcontext;
252  funcctx = SRF_FIRSTCALL_INIT();
253  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
254 
255  process(
256  text_to_cstring(PG_GETARG_TEXT_P(0)),
257  text_to_cstring(PG_GETARG_TEXT_P(1)),
258  text_to_cstring(PG_GETARG_TEXT_P(2)),
259  text_to_cstring(PG_GETARG_TEXT_P(3)),
260 
261  PG_GETARG_FLOAT8(4),
262  PG_GETARG_INT32(5),
263  PG_GETARG_INT64(6),
264 
265  PG_GETARG_BOOL(7),
266  PG_GETARG_INT32(8),
267  PG_GETARG_BOOL(9),
268 
269  &result_tuples,
270  &result_count);
271 
272  /*********************************************************************/
273 
274 #if PGSQL_VERSION > 95
275  funcctx->max_calls = result_count;
276 #else
277  funcctx->max_calls = (uint32_t)result_count;
278 #endif
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 = (Short_vehicle_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 = 3;
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] = Int64GetDatum(result_tuples[call_cntr].vehicle_id);
315  values[2] = Int64GetDatum(result_tuples[call_cntr].order_id);
316 
317  /*********************************************************************/
318 
319  tuple = heap_form_tuple(tuple_desc, values, nulls);
320  result = HeapTupleGetDatum(tuple);
321 
322  pfree(values); values = NULL;
323  pfree(nulls); nulls = NULL;
324 
325  SRF_RETURN_NEXT(funcctx, result);
326  } else {
327  if (result_tuples) {pfree(result_tuples); result_tuples = NULL;}
328  funcctx->user_fctx = NULL;
329  SRF_RETURN_DONE(funcctx);
330  }
331 }
time_msg.h
pickDeliveryOrders_t.h
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
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)
Definition: optimize_driver.cpp:350
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
PG_FUNCTION_INFO_V1
PG_FUNCTION_INFO_V1(_vrp_optimize)
_vrp_optimize
PGDLLEXPORT Datum _vrp_optimize(PG_FUNCTION_ARGS)
Definition: optimize.c:241
Time_multipliers_t
Time Dependant Multipliers.
Definition: time_multipliers_t.h:46
short_vehicle_rt.h
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
PGR_DBG
#define PGR_DBG(...)
Definition: debug_macro.h:34
process
static void process(char *pd_orders_sql, char *vehicles_sql, char *matrix_sql, char *multipliers_sql, double factor, int max_cycles, int64_t execution_date, bool check_triangle_inequality, int subdivision_kind, bool use_timestamps, Short_vehicle_rt **result_tuples, size_t *result_count)
Definition: optimize.c:49
Short_vehicle_rt
short_vehicle
Definition: short_vehicle_rt.h:40
if
if(DOXYGEN_FOUND) configure_file($
Definition: doxygen/CMakeLists.txt:13
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
time_multipliers_input.h
optimize_driver.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
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