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
eucledianTSP.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: eucledianTSP.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/coordinates_input.h"
47 #include "./eucledianTSP_driver.h"
48 
49 
50 
51 PGDLLEXPORT Datum eucledianTSP(PG_FUNCTION_ARGS);
52 
53 /******************************************************************************/
54 /* MODIFY AS NEEDED */
55 static
56 void
58  char* coordinates_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  if (initial_temperature < final_temperature) {
82  elog(ERROR, "Condition not met: initial_temperature > final_temperature");
83  }
84  if (final_temperature <= 0) {
85  elog(ERROR, "Condition not met: final_temperature > 0");
86  }
87  if (cooling_factor <=0 || cooling_factor >=1) {
88  elog(ERROR, "Condition not met: 0 < cooling_factor < 1");
89  }
90  if (tries_per_temperature < 0) {
91  elog(ERROR, "Condition not met: tries_per_temperature >= 0");
92  }
93  if (max_changes_per_temperature < 1) {
94  elog(ERROR, "Condition not met: max_changes_per_temperature > 0");
95  }
96  if (max_consecutive_non_changes < 1) {
97  elog(ERROR, "Condition not met: max_consecutive_non_changes > 0");
98  }
99  if (time_limit < 0) {
100  elog(ERROR, "Condition not met: max_processing_time >= 0");
101  }
102 
103 
104  Coordinate_t *coordinates = NULL;
105  size_t total_coordinates = 0;
106  pgr_get_coordinates(coordinates_sql, &coordinates, &total_coordinates);
107 
108  if (total_coordinates == 0) {
109  PGR_DBG("No coordinates found");
110  (*result_count) = 0;
111  (*result_tuples) = NULL;
112  pgr_SPI_finish();
113  return;
114  }
115 
116  char *err_msg = NULL;
117  char *log_msg = NULL;
118  clock_t start_t = clock();
120  coordinates,
121  total_coordinates,
122  start_vid,
123  end_vid,
124  initial_temperature,
125  final_temperature,
126  cooling_factor,
127  tries_per_temperature,
128  max_changes_per_temperature,
129  max_consecutive_non_changes,
130  randomize,
131  time_limit,
132  result_tuples,
133  result_count,
134  &log_msg,
135  &err_msg);
136  time_msg(" processing eucledianTSP", start_t, clock());
137  if (log_msg) {
138  elog(NOTICE, "%s", log_msg);
139  free(log_msg);
140  }
141  if (err_msg) {
142  if (*result_tuples) free(*result_tuples);
143  elog(ERROR, "%s", err_msg);
144  free(err_msg);
145  }
146 
147  pfree(coordinates);
148  pgr_SPI_finish();
149 }
150 /* */
151 /******************************************************************************/
152 
154 PGDLLEXPORT Datum
155 eucledianTSP(PG_FUNCTION_ARGS) {
156  FuncCallContext *funcctx;
157  uint32_t call_cntr;
158  uint32_t max_calls;
159  TupleDesc tuple_desc;
160 
161  /**************************************************************************/
162  /* MODIFY AS NEEDED */
163  /* */
164  General_path_element_t *result_tuples = NULL;
165  size_t result_count = 0;
166  /* */
167  /**************************************************************************/
168 
169  if (SRF_IS_FIRSTCALL()) {
170  MemoryContext oldcontext;
171  funcctx = SRF_FIRSTCALL_INIT();
172  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
173 
174 
175  /**********************************************************************/
176  /* MODIFY AS NEEDED */
177  /*
178 
179  CREATE OR REPLACE FUNCTION pgr_eucledianTSP(
180  coordinates_sql TEXT,
181  start_id BIGINT DEFAULT 0,
182  end_id BIGINT DEFAULT 0,
183 
184  max_processing_time FLOAT DEFAULT '+infinity'::FLOAT,
185 
186  tries_per_temperature INTEGER DEFAULT 500,
187  max_changes_per_temperature INTEGER DEFAULT 60,
188  max_consecutive_non_changes INTEGER DEFAULT 200,
189 
190  initial_temperature FLOAT DEFAULT 100,
191  final_temperature FLOAT DEFAULT 0.1,
192  cooling_factor FLOAT DEFAULT 0.9,
193 
194  randomize BOOLEAN DEFAULT true,
195  */
196 
197  process(
198  pgr_text2char(PG_GETARG_TEXT_P(0)),
199  PG_GETARG_INT64(1),
200  PG_GETARG_INT64(2),
201 
202  PG_GETARG_FLOAT8(3),
203 
204  PG_GETARG_INT32(4),
205  PG_GETARG_INT32(5),
206  PG_GETARG_INT32(6),
207 
208  PG_GETARG_FLOAT8(7),
209  PG_GETARG_FLOAT8(8),
210  PG_GETARG_FLOAT8(9),
211 
212  PG_GETARG_BOOL(10),
213  &result_tuples,
214  &result_count);
215  /* */
216  /**********************************************************************/
217 
218  funcctx->max_calls = (uint32_t) result_count;
219  funcctx->user_fctx = result_tuples;
220  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
221  != TYPEFUNC_COMPOSITE) {
222  ereport(ERROR,
223  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
224  errmsg("function returning record called in context "
225  "that cannot accept type record")));
226  }
227 
228  funcctx->tuple_desc = tuple_desc;
229  MemoryContextSwitchTo(oldcontext);
230  }
231 
232  funcctx = SRF_PERCALL_SETUP();
233  call_cntr = funcctx->call_cntr;
234  max_calls = funcctx->max_calls;
235  tuple_desc = funcctx->tuple_desc;
236  result_tuples = (General_path_element_t*) funcctx->user_fctx;
237 
238  if (call_cntr < max_calls) {
239  HeapTuple tuple;
240  Datum result;
241  Datum *values;
242  bool* nulls;
243 
244  /**********************************************************************/
245  /* MODIFY AS NEEDED */
246  // OUT seq INTEGER,
247  // OUT node BIGINT,
248  // OUT cost FLOAT,
249  // OUT agg_cost FLOAT
250 
251  values = palloc(4 * sizeof(Datum));
252  nulls = palloc(4 * sizeof(bool));
253 
254 
255  size_t i;
256  for (i = 0; i < 4; ++i) {
257  nulls[i] = false;
258  }
259 
260  // postgres starts counting from 1
261  values[0] = Int32GetDatum(call_cntr + 1);
262  values[1] = Int64GetDatum(result_tuples[call_cntr].node);
263  values[2] = Float8GetDatum(result_tuples[call_cntr].cost);
264  values[3] = Float8GetDatum(result_tuples[call_cntr].agg_cost);
265  /**********************************************************************/
266 
267  tuple = heap_form_tuple(tuple_desc, values, nulls);
268  result = HeapTupleGetDatum(tuple);
269  SRF_RETURN_NEXT(funcctx, result);
270  } else {
271  // cleanup
272  if (result_tuples) free(result_tuples);
273 
274  SRF_RETURN_DONE(funcctx);
275  }
276 }
277 
#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
PG_FUNCTION_INFO_V1(eucledianTSP)
void pgr_get_coordinates(char *sql, Coordinate_t **coordinates, size_t *total_coordinates)
bigint id, float x, float y,
void pgr_SPI_finish(void)
void pgr_SPI_connect(void)
void do_pgr_eucledianTSP(Coordinate_t *coordinates_data, size_t total_coordinates, 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 *coordinates_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: eucledianTSP.c:57
PGDLLEXPORT Datum eucledianTSP(PG_FUNCTION_ARGS)
Definition: eucledianTSP.c:155
char * err_msg
Definition: BDATester.cpp:50
char * pgr_text2char(text *in)