pgRouting
pgRouting extends the PostGIS / PostgreSQL geospatial database to provide geospatial routing functionality.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
newTSP.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: newTSP.c
3 
4 Generated with Template by:
5 Copyright (c) 2015 pgRouting developers
6 Mail: project@pgrouting.org
7 
8 Function's developer:
9 Copyright (c) 2015 Celia Virginia Vergara Castillo
10 Mail: vicky_vergara@hotmail.com
11 
12 ------
13 
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18 
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23 
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 
28  ********************************************************************PGR-GNU*/
29 
30 #include "postgres.h"
31 #include "executor/spi.h"
32 #include "funcapi.h"
33 #include "utils/array.h"
34 #include "catalog/pg_type.h"
35 #if PGSQL_VERSION > 92
36 #include "access/htup_details.h"
37 #endif
38 #include "fmgr.h"
39 
40 #define DEBUG
41 
42 #include "./../../common/src/debug_macro.h"
43 #include "./../../common/src/time_msg.h"
44 #include "./../../common/src/pgr_types.h"
45 #include "./../../common/src/postgres_connection.h"
46 #include "./../../common/src/matrixRows_input.h"
47 #include "./newTSP_driver.h"
48 
49 
50 
51 PGDLLEXPORT Datum newTSP(PG_FUNCTION_ARGS);
52 
53 /******************************************************************************/
54 /* MODIFY AS NEEDED */
55 static
56 void
58  char* distances_sql,
59  int64_t start_vid,
60  int64_t end_vid,
61 
62  double time_limit,
63 
64  int64_t tries_per_temperature,
65  int64_t max_changes_per_temperature,
66  int64_t max_consecutive_non_changes,
67 
68  double initial_temperature,
69  double final_temperature,
70  double cooling_factor,
71 
72  bool randomize,
73 
74  General_path_element_t **result_tuples,
75  size_t *result_count) {
77 
78  /*
79  * errors in parameters
80  */
81 
82  if (initial_temperature < final_temperature) {
83  elog(ERROR, "Condition not met: initial_temperature > final_temperature");
84  }
85  if (final_temperature <= 0) {
86  elog(ERROR, "Condition not met: final_temperature > 0");
87  }
88  if (cooling_factor <=0 || cooling_factor >=1) {
89  elog(ERROR, "Condition not met: 0 < cooling_factor < 1");
90  }
91  if (tries_per_temperature < 0) {
92  elog(ERROR, "Condition not met: tries_per_temperature >= 0");
93  }
94  if (max_changes_per_temperature < 1) {
95  elog(ERROR, "Condition not met: max_changes_per_temperature > 0");
96  }
97  if (max_consecutive_non_changes < 1) {
98  elog(ERROR, "Condition not met: max_consecutive_non_changes > 0");
99  }
100  if (time_limit < 0) {
101  elog(ERROR, "Condition not met: max_processing_time >= 0");
102  }
103 
104 
105  Matrix_cell_t *distances = NULL;
106  size_t total_distances = 0;
107  pgr_get_matrixRows(distances_sql, &distances, &total_distances);
108 
109  if (total_distances == 0) {
110  PGR_DBG("No distances found");
111  (*result_count) = 0;
112  (*result_tuples) = NULL;
113  pgr_SPI_finish();
114  return;
115  }
116 
117  char *err_msg = NULL;
118  char *log_msg = NULL;
119  clock_t start_t = clock();
120  do_pgr_tsp(
121  distances,
122  total_distances,
123  start_vid,
124  end_vid,
125  initial_temperature,
126  final_temperature,
127  cooling_factor,
128  tries_per_temperature,
129  max_changes_per_temperature,
130  max_consecutive_non_changes,
131  randomize,
132  time_limit,
133  result_tuples,
134  result_count,
135  &log_msg,
136  &err_msg);
137  time_msg(" processing eucledianTSP", start_t, clock());
138  if (log_msg) {
139  elog(NOTICE, "%s", log_msg);
140  free(log_msg);
141  }
142  if (err_msg) {
143  if (*result_tuples) free(*result_tuples);
144  elog(ERROR, "%s", err_msg);
145  free(err_msg);
146  }
147 
148  pfree(distances);
149  pgr_SPI_finish();
150 }
151 /* */
152 /******************************************************************************/
153 
155 PGDLLEXPORT Datum
156 newTSP(PG_FUNCTION_ARGS) {
157  FuncCallContext *funcctx;
158  uint32_t call_cntr;
159  uint32_t max_calls;
160  TupleDesc tuple_desc;
161 
162  /**************************************************************************/
163  /* MODIFY AS NEEDED */
164  /* */
165  General_path_element_t *result_tuples = NULL;
166  size_t result_count = 0;
167  /* */
168  /**************************************************************************/
169 
170  if (SRF_IS_FIRSTCALL()) {
171  MemoryContext oldcontext;
172  funcctx = SRF_FIRSTCALL_INIT();
173  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
174 
175 
176  /**********************************************************************/
177  /* MODIFY AS NEEDED */
178  /*
179 
180  CREATE OR REPLACE FUNCTION pgr_newTSP(
181  matrix_row_sql TEXT,
182  start_id BIGINT DEFAULT 0,
183  end_id BIGINT DEFAULT 0,
184 
185  max_processing_time FLOAT DEFAULT '+infinity'::FLOAT,
186 
187  tries_per_temperature INTEGER DEFAULT 500,
188  max_changes_per_temperature INTEGER DEFAULT 60,
189  max_consecutive_non_changes INTEGER DEFAULT 200,
190 
191  initial_temperature FLOAT DEFAULT 100,
192  final_temperature FLOAT DEFAULT 0.1,
193  cooling_factor FLOAT DEFAULT 0.9,
194 
195  randomize BOOLEAN DEFAULT true,
196  */
197 
198  process(
199  pgr_text2char(PG_GETARG_TEXT_P(0)),
200  PG_GETARG_INT64(1),
201  PG_GETARG_INT64(2),
202 
203  PG_GETARG_FLOAT8(3),
204 
205  PG_GETARG_INT32(4),
206  PG_GETARG_INT32(5),
207  PG_GETARG_INT32(6),
208 
209  PG_GETARG_FLOAT8(7),
210  PG_GETARG_FLOAT8(8),
211  PG_GETARG_FLOAT8(9),
212 
213  PG_GETARG_BOOL(10),
214  &result_tuples,
215  &result_count);
216  /* */
217  /**********************************************************************/
218 
219  funcctx->max_calls = (uint32_t) result_count;
220  funcctx->user_fctx = result_tuples;
221  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
222  != TYPEFUNC_COMPOSITE) {
223  ereport(ERROR,
224  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
225  errmsg("function returning record called in context "
226  "that cannot accept type record")));
227  }
228 
229  funcctx->tuple_desc = tuple_desc;
230  MemoryContextSwitchTo(oldcontext);
231  }
232 
233  funcctx = SRF_PERCALL_SETUP();
234  call_cntr = funcctx->call_cntr;
235  max_calls = funcctx->max_calls;
236  tuple_desc = funcctx->tuple_desc;
237  result_tuples = (General_path_element_t*) funcctx->user_fctx;
238 
239  if (call_cntr < max_calls) {
240  HeapTuple tuple;
241  Datum result;
242  Datum *values;
243  bool* nulls;
244 
245  /**********************************************************************/
246  /* MODIFY AS NEEDED */
247  // OUT seq INTEGER,
248  // OUT node BIGINT,
249  // OUT cost FLOAT,
250  // OUT agg_cost FLOAT
251 
252  values = palloc(4 * sizeof(Datum));
253  nulls = palloc(4 * sizeof(bool));
254 
255 
256  size_t i;
257  for (i = 0; i < 4; ++i) {
258  nulls[i] = false;
259  }
260 
261  // postgres starts counting from 1
262  values[0] = Int32GetDatum(call_cntr + 1);
263  values[1] = Int64GetDatum(result_tuples[call_cntr].node);
264  values[2] = Float8GetDatum(result_tuples[call_cntr].cost);
265  values[3] = Float8GetDatum(result_tuples[call_cntr].agg_cost);
266  /**********************************************************************/
267 
268  tuple = heap_form_tuple(tuple_desc, values, nulls);
269  result = HeapTupleGetDatum(tuple);
270  SRF_RETURN_NEXT(funcctx, result);
271  } else {
272  // cleanup
273  if (result_tuples) free(result_tuples);
274 
275  SRF_RETURN_DONE(funcctx);
276  }
277 }
278 
PGDLLEXPORT Datum newTSP(PG_FUNCTION_ARGS)
Definition: newTSP.c:156
#define PGR_DBG(...)
Definition: debug_macro.h:33
void time_msg(char *msg, clock_t start_t, clock_t end_t)
Definition: time_msg.c:31
void pgr_SPI_finish(void)
void pgr_SPI_connect(void)
void do_pgr_tsp(Matrix_cell_t *distances, size_t total_distances, int64_t start_vid, int64_t end_vid, double initial_temperature, double final_temperature, double cooling_factor, int64_t tries_per_temperature, int64_t max_changes_per_temperature, int64_t max_consecutive_non_changes, bool randomize, double time_limit, General_path_element_t **return_tuples, size_t *return_count, char **log_msg, char **err_msg)
static void process(char *distances_sql, int64_t start_vid, int64_t end_vid, double time_limit, int64_t tries_per_temperature, int64_t max_changes_per_temperature, int64_t max_consecutive_non_changes, double initial_temperature, double final_temperature, double cooling_factor, bool randomize, General_path_element_t **result_tuples, size_t *result_count)
Definition: newTSP.c:57
void pgr_get_matrixRows(char *sql, Matrix_cell_t **rows, size_t *total_rows)
bigint start_vid, bigint end_vid, float agg_cost,
char * err_msg
Definition: BDATester.cpp:50
PG_FUNCTION_INFO_V1(newTSP)
char * pgr_text2char(text *in)