PGROUTING  3.2
euclideanTSP.c
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: euclideanTSP.c
3 
4 Generated with Template by:
5 Copyright (c) 2015 pgRouting developers
7 
8 Function's developer:
9 Copyright (c) 2015 Celia Virginia Vergara Castillo
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 
31 #include "utils/array.h"
32 
33 #include "c_common/debug_macro.h"
34 #include "c_common/e_report.h"
35 #include "c_common/time_msg.h"
36 
39 
40 
41 
42 PGDLLEXPORT Datum _pgr_tspeuclidean(PG_FUNCTION_ARGS);
43 
44 /******************************************************************************/
45 /* MODIFY AS NEEDED */
46 static
47 void
49  char* coordinates_sql,
50  int64_t start_vid,
51  int64_t end_vid,
52 
53  double time_limit,
54 
55  int64_t tries_per_temperature,
56  int64_t max_changes_per_temperature,
57  int64_t max_consecutive_non_changes,
58 
59  double initial_temperature,
60  double final_temperature,
61  double cooling_factor,
62 
63  bool randomize,
64 
65  General_path_element_t **result_tuples,
66  size_t *result_count) {
68 
69  /*
70  * errors in parameters
71  */
72  if (initial_temperature < final_temperature) {
73  elog(ERROR, "Condition not met: initial_temperature"
74  " > final_temperature");
75  }
76  if (final_temperature <= 0) {
77  elog(ERROR, "Condition not met: final_temperature > 0");
78  }
79  if (cooling_factor <=0 || cooling_factor >=1) {
80  elog(ERROR, "Condition not met: 0 < cooling_factor < 1");
81  }
82  if (tries_per_temperature < 0) {
83  elog(ERROR, "Condition not met: tries_per_temperature >= 0");
84  }
85  if (max_changes_per_temperature < 1) {
86  elog(ERROR, "Condition not met: max_changes_per_temperature > 0");
87  }
88  if (max_consecutive_non_changes < 1) {
89  elog(ERROR, "Condition not met: max_consecutive_non_changes > 0");
90  }
91  if (time_limit < 0) {
92  elog(ERROR, "Condition not met: max_processing_time >= 0");
93  }
94 
95 
96  Coordinate_t *coordinates = NULL;
97  size_t total_coordinates = 0;
98  pgr_get_coordinates(coordinates_sql, &coordinates, &total_coordinates);
99 
100  if (total_coordinates == 0) {
101  PGR_DBG("No coordinates found");
102  (*result_count) = 0;
103  (*result_tuples) = NULL;
104  pgr_SPI_finish();
105  return;
106  }
107 
108  PGR_DBG("Starting timer");
109  clock_t start_t = clock();
110  char* log_msg = NULL;
111  char* notice_msg = NULL;
112  char* err_msg = NULL;
113 
115  coordinates, total_coordinates,
116  start_vid,
117  end_vid,
118  initial_temperature,
119  final_temperature,
120  cooling_factor,
121  tries_per_temperature,
122  max_changes_per_temperature,
123  max_consecutive_non_changes,
124  randomize,
125  time_limit,
126  result_tuples,
127  result_count,
128  &log_msg,
129  &notice_msg,
130  &err_msg);
131 
132  time_msg("euclideanTSP", start_t, clock());
133 
134  if (err_msg && (*result_tuples)) {
135  pfree(*result_tuples);
136  (*result_tuples) = NULL;
137  (*result_count) = 0;
138  }
139 
140  pgr_global_report(log_msg, notice_msg, err_msg);
141 
142  if (log_msg) pfree(log_msg);
143  if (notice_msg) pfree(notice_msg);
144  if (err_msg) pfree(err_msg);
145  if (coordinates) pfree(coordinates);
146 
147  pgr_SPI_finish();
148 }
149 /* */
150 /******************************************************************************/
151 
153 PGDLLEXPORT Datum
154 _pgr_tspeuclidean(PG_FUNCTION_ARGS) {
155  FuncCallContext *funcctx;
156  TupleDesc tuple_desc;
157 
158  /**************************************************************************/
159  /* MODIFY AS NEEDED */
160  /* */
161  General_path_element_t *result_tuples = NULL;
162  size_t result_count = 0;
163  /* */
164  /**************************************************************************/
165 
166  if (SRF_IS_FIRSTCALL()) {
167  MemoryContext oldcontext;
168  funcctx = SRF_FIRSTCALL_INIT();
169  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
170 
171 
172  /**********************************************************************/
173  /* MODIFY AS NEEDED */
174  /*
175 
176  CREATE OR REPLACE FUNCTION pgr_euclideanTSP(
177  coordinates_sql TEXT,
178  start_id BIGINT DEFAULT 0,
179  end_id BIGINT DEFAULT 0,
180 
181  max_processing_time FLOAT DEFAULT '+infinity'::FLOAT,
182 
183  tries_per_temperature INTEGER DEFAULT 500,
184  max_changes_per_temperature INTEGER DEFAULT 60,
185  max_consecutive_non_changes INTEGER DEFAULT 200,
186 
187  initial_temperature FLOAT DEFAULT 100,
188  final_temperature FLOAT DEFAULT 0.1,
189  cooling_factor FLOAT DEFAULT 0.9,
190 
191  randomize BOOLEAN DEFAULT true,
192  */
193 
194  process(
195  text_to_cstring(PG_GETARG_TEXT_P(0)),
196  PG_GETARG_INT64(1),
197  PG_GETARG_INT64(2),
198 
199  PG_GETARG_FLOAT8(3),
200 
201  PG_GETARG_INT32(4),
202  PG_GETARG_INT32(5),
203  PG_GETARG_INT32(6),
204 
205  PG_GETARG_FLOAT8(7),
206  PG_GETARG_FLOAT8(8),
207  PG_GETARG_FLOAT8(9),
208 
209  PG_GETARG_BOOL(10),
210  &result_tuples,
211  &result_count);
212  /* */
213  /**********************************************************************/
214 
215 #if PGSQL_VERSION > 95
216  funcctx->max_calls = result_count;
217 #else
218  funcctx->max_calls = (uint32_t)result_count;
219 #endif
220 
221  funcctx->user_fctx = result_tuples;
222  if (get_call_result_type(fcinfo, NULL, &tuple_desc)
223  != TYPEFUNC_COMPOSITE) {
224  ereport(ERROR,
225  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
226  errmsg("function returning record called in context "
227  "that cannot accept type record")));
228  }
229 
230  funcctx->tuple_desc = tuple_desc;
231  MemoryContextSwitchTo(oldcontext);
232  }
233 
234  funcctx = SRF_PERCALL_SETUP();
235  tuple_desc = funcctx->tuple_desc;
236  result_tuples = (General_path_element_t*) funcctx->user_fctx;
237 
238  if (funcctx->call_cntr < funcctx->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(funcctx->call_cntr + 1);
262  values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].node);
263  values[2] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost);
264  values[3] = Float8GetDatum(result_tuples[funcctx->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  SRF_RETURN_DONE(funcctx);
272  }
273 }
PG_FUNCTION_INFO_V1
PG_FUNCTION_INFO_V1(_pgr_tspeuclidean)
time_msg.h
postgres_connection.h
pgr_SPI_connect
void pgr_SPI_connect(void)
Definition: postgres_connection.c:82
pgr_SPI_finish
void pgr_SPI_finish(void)
Definition: postgres_connection.c:71
e_report.h
pgr_get_coordinates
void pgr_get_coordinates(char *sql, Coordinate_t **coordinates, size_t *total_coordinates)
bigint id, float x, float y,
Definition: coordinates_input.c:57
coordinates_input.h
debug_macro.h
Coordinate_t
Definition: coordinate_t.h:37
euclideanTSP_driver.h
PGR_DBG
#define PGR_DBG(...)
Definition: debug_macro.h:34
process
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: euclideanTSP.c:48
General_path_element_t::node
int64_t node
Definition: general_path_element_t.h:41
General_path_element_t
Definition: general_path_element_t.h:37
if
if(DOXYGEN_FOUND) configure_file($
Definition: doxygen/CMakeLists.txt:13
do_pgr_euclideanTSP
void do_pgr_euclideanTSP(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 **notice_msg, char **err_msg)
Definition: euclideanTSP_driver.cpp:45
time_msg
void time_msg(char *msg, clock_t start_t, clock_t end_t)
Definition: time_msg.c:32
General_path_element_t::cost
double cost
Definition: general_path_element_t.h:43
pgr_global_report
void pgr_global_report(char *log, char *notice, char *err)
notice & error
Definition: e_report.c:93
General_path_element_t::agg_cost
double agg_cost
Definition: general_path_element_t.h:44
_pgr_tspeuclidean
PGDLLEXPORT Datum _pgr_tspeuclidean(PG_FUNCTION_ARGS)
Definition: euclideanTSP.c:154