PGROUTING  2.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
performance/dijkstra/pgRouting.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 
3 Copyright (c) 2015 pgRouting developers
4 Mail: project@pgrouting.org
5 
6 ------
7 
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 
22 ********************************************************************PGR-GNU*/
23 
24 #include <boost/config.hpp>
25 #include <string>
26 #include <boost/program_options.hpp>
27 namespace po = boost::program_options;
28 
29 #include <boost/graph/adjacency_list.hpp>
30 
31 #include <iostream>
32 #include <sstream>
33 #include <fstream>
34 #include <deque>
35 #include <unistd.h>
36 #include <libpq-fe.h>
37 
38 
39 #include "postgres.h"
40 #include "./../../../../common/src/pgr_types.h"
41 #include "./../../../../common/src/basePath_SSEC.hpp"
42 #include "./../../../../common/src/baseGraph.hpp"
43 #include "./../../../../dijkstra/src/pgr_dijkstra.hpp"
44 #include "./dijkstra.hpp"
45 
46 
47 
48 /****************************************
49  SIMULATES THE C CODE THAT LOADS THE DATA
50  ****************************************/
51 void import_from_file(const std::string &input_file_name, pgr_edge_t *edges, unsigned int *count, int64_t start_vertex, int64_t end_vertex, bool &found) {
52  const char* file_name = input_file_name.c_str();
53 
54  std::ifstream ifs(file_name);
55  if (!ifs) {
56  std::cerr << "The file " << file_name << " can not be opened!" << std::endl;
57  exit(1);
58  }
59 
60  ifs >> (*count);
61 
62  long edge_id; // , start_id, end_id;
63  //double edge_weight, reverse_weight;
64  bool s_found = false;
65  bool t_found = false;
66 
67  unsigned int i = 0;
68  while (i < (*count) && ifs >> edge_id) {
69  if (edge_id == -1) break;
70  edges[i].id = edge_id;
71  ifs >> edges[i].source;
72  ifs >> edges[i].target;
73  ifs >> edges[i].cost;
74  ifs >> edges[i].reverse_cost;
75  // when loading checking if start and end are found
76  if (!s_found)
77  s_found = ((edges[i].source == start_vertex) || (edges[i].target == end_vertex));
78  if (!t_found)
79  t_found = ((edges[i].source == end_vertex) || (edges[i].target == end_vertex));
80  i++;
81  }
82  ifs.close();
83  found = s_found && t_found;
84 }
85 
86 void get_options_description(po::options_description &od_desc) {
87  od_desc.add_options()
88  ("help", "Produce this help message.")
89  ("test,t", po::value<bool>()->default_value(true),
90  "For testing purposes.")
91  ("dbname,d", po::value<std::string>()->required(),
92  "Specifies the name of the database to connect to.")
93  ("host,h", po::value<std::string>()->default_value("localhost"),
94  "Specifies the host name of the machine on which the server is running.")
95  ("port,p", po::value<std::string>()->default_value("5432"),
96  "Port number to connect to at the server host.")
97  ("username,U", po::value<std::string>()->default_value(getlogin()),
98  "Connect to the database as the user username instead of the default.\n (You must have permission to do so, of course.)")
99  ("password,W", po::value<std::string>()->default_value(""),
100  "User's the password.\n")
101  ;
102 }
103 
104 
106  po::variables_map &vm,
107  po::options_description &od_desc) {
108 
109  if (vm.count("help")) {
110  std::cout << od_desc << "\n";
111  return 0;
112  }
113 
114  if (vm.count("dbname"))
115  std::cout << "dbname = " << vm["dbname"].as<std::string>() << "\n";
116  else
117  std::cout << "Parameter: dbname missing\n";
118 
119  if (vm.count("host"))
120  std::cout << "host = " << vm["host"].as<std::string>() << "\n";
121  else
122  std::cout << "Parameter: host missing\n";
123 
124  if (vm.count("port"))
125  std::cout << "port = " << vm["port"].as<std::string>() << "\n";
126  else
127  std::cout << "Parameter: port missing\n";
128 
129  if (vm.count("username"))
130  std::cout << "username = " << vm["username"].as<std::string>() << "\n";
131  else
132  std::cout << "Parameter: username missing\n";
133 
134  if (vm.count("password"))
135  std::cout << "password = " << vm["password"].as<std::string>() << "\n";
136  else
137  std::cout << "Parameter: password missing\n";
138 
139  if (vm.count("dbname") & vm.count("username") & vm.count("host") & vm.count("password")) {
140  std::cout << "Parameters: \n"
141  << vm["dbname"].as<std::string>() << "\n"
142  << vm["username"].as<std::string>() << "\n"
143  << vm["password"].as<std::string>() << "\n"
144  << vm["host"].as<std::string>() << ".\n";
145  return 2;
146  } else {
147  std::cout << "Missing parameter.\n";
148  std::cout << od_desc << "\n";
149  return 1;
150  }
151 }
152 
153 
154  static void
156 {
157  PQfinish(conn);
158  exit(1);
159 }
160 
161 
162 
163 template <typename G>
164 void process(G graph, pgr_edge_t *data_edges, int row_count) {
165  graph.graph_insert_data(data_edges, row_count);
166  std::vector<int64_t> targets;
167  std::string::size_type sz;
168 
169 
170  // read the command and break into tokens
171  std::string cmd;
172  std::string buf;
173  std::vector<std::string> tokens;
174  while (true) {
175  std::cout << "\n\n\n\n\t\t COMMANDS\n\n "
176 
177  << "\n\tDIJKSTRA\n"
178  << "(Input the command separating with spaces)\n"
179  << "\tdijkstra from to \n"
180  << "\tdijkstra from to1 to2 to3\n\n"
181 
182  << "\n\tFINISH\n"
183  << "\tend\n\n"
184  << ">>>";
185  tokens.clear();
186  targets.clear();
187  cmd = "";
188  std::getline(std::cin, cmd);
189  std::stringstream ss(cmd);
190  while (ss >> buf) {
191  tokens.push_back(buf);
192  }
193 
194  if (tokens.size() == 0) {
195  std::cout << "No command received\n";
196  continue;
197  }
198 
199  if (tokens[0].compare("end")==0) return;
200 
201  if (tokens[0].compare("dijkstra") != 0) {
202  std::cout << "Command: " << cmd << " not found\n";
203  continue;
204  }
205 
206 
207  if (tokens[0].compare("dijkstra") == 0) {
208  process_dijkstra(graph, tokens);
209  }
210  }
211 }
212 
213 
214 
215 int main(int ac, char* av[]) {
216  po::options_description od_desc("Allowed options");
217  get_options_description(od_desc);
218 
219  po::variables_map vm;
220  po::store(po::parse_command_line(ac, av, od_desc), vm);
221  if (vm.count("help")) {
222  std::cout << od_desc << "\n";
223  return 0;
224  }
225 
226  try{
227  po::notify(vm);
228  }
229  catch(...){
230  std::cout << od_desc << "\n";
231  return 0;
232  }
233 
234  auto ret_val = process_command_line(vm, od_desc);
235  if (ret_val != 2) return ret_val;
236 
237 
238  auto db_dbase(vm["dbname"].as<std::string>());
239  auto db_host(vm["host"].as<std::string>());
240  auto db_port(vm["port"].as<std::string>());
241  auto db_username(vm["username"].as<std::string>());
242  auto db_pwd(vm["password"].as<std::string>());
243  auto test(vm["test"].as<bool>());
244  auto db_conn = "host=" + db_host
245  + " user=" + db_username
246  + " dbname=" + db_dbase
247  + " port=" + db_port
248  + " password=" + db_pwd;
249 
250  std::cout << "connection: " << db_conn <<"\n";
251 
252  const char *conninfo = db_conn.c_str();
253  PGconn *conn;
254  PGresult *res;
255  int rec_count, col_count;
256 
257 
258  conn = PQconnectdb(conninfo);
259  /* Check to see that the backend connection was successfully made */
260  if (PQstatus(conn) != CONNECTION_OK)
261  {
262  fprintf(stderr, "Connection to database failed: %s",
263  PQerrorMessage(conn));
264  exit_nicely(conn);
265  exit(0);
266  }
267 
268  std::string data_sql;
269  if (test) {
270  data_sql = "select id, source, target, cost, reverse_cost from edge_table order by id";
271  } else {
272  std::cout << "Input data query: ";
273  std::getline (std::cin,data_sql);
274  }
275  std::cout << "\nThe data is from:" << data_sql <<"\n";
276 
277  res = PQexec(conn, data_sql.c_str());
278 
279  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
280  std::cout << "We did not get any data!\n";
281  exit_nicely(conn);
282  exit(1);
283  }
284 
285  rec_count = PQntuples(res);
286  col_count = PQnfields(res);
287  if (col_count > 5 || col_count < 4) {
288  std::cout << "Max number of columns 5\n";
289  std::cout << "Min number of columns 4\n";
290  exit_nicely(conn);
291  exit(1);
292  }
293 
294  auto id_fnum = PQfnumber(res, "id");
295  auto source_fnum = PQfnumber(res, "source");
296  auto target_fnum = PQfnumber(res, "target");
297  auto cost_fnum = PQfnumber(res, "cost");
298  auto reverse_fnum = PQfnumber(res, "reverse_cost");
299 
300 
301 
302  pgr_edge_t *data_edges;
303  data_edges = (pgr_edge_t *) malloc(rec_count * sizeof(pgr_edge_t));
304 
305 
306  printf("We received %d records.\n", rec_count);
307  puts("==========================");
308 
309 
310 
311  std::string::size_type sz;
312  std::string str;
313 
314  for (int row = 0; row < rec_count; ++row) {
315  str = std::string(PQgetvalue(res, row, id_fnum));
316  data_edges[row].id = stol(str, &sz);
317 
318  str = std::string(PQgetvalue(res, row, source_fnum));
319  data_edges[row].source = stol(str, &sz);
320 
321  str = std::string(PQgetvalue(res, row, target_fnum));
322  data_edges[row].target = stol(str, &sz);
323 
324  str = std::string(PQgetvalue(res, row, cost_fnum));
325  data_edges[row].cost = stod(str, &sz);
326 
327  if (reverse_fnum != -1) {
328  str = std::string(PQgetvalue(res, row, reverse_fnum));
329  data_edges[row].reverse_cost = stod(str, &sz);
330  }
331 #if 0
332  std::cout << "\tid: " << data_edges[row].id << "\t";
333  std::cout << "\tsource: " << data_edges[row].source << "\t";
334  std::cout << "\ttarget: " << data_edges[row].target << "\t";
335  std::cout << "\tcost: " << data_edges[row].cost << "\t";
336  if (reverse_fnum != -1) {
337  std::cout << "\treverse: " << data_edges[row].reverse_cost << "\t";
338  }
339  std::cout << "\n";
340 #endif
341  }
342 
343 
344  puts("==========================");
345 
346  PQclear(res);
347 
348  PQfinish(conn);
349 
350 
352 
353  std::string directed;
354  std::cout << "Is the graph directed [N,n]? default[Y]";
355  std::getline(std::cin,directed);
356  graphType gType = (directed.compare("N")==0 || directed.compare("n")==0)? UNDIRECTED: DIRECTED;
357  bool directedFlag = (directed.compare("N")==0 || directed.compare("n")==0)? false: true;
358 
359 
360  const int initial_size = rec_count;
361 
362 
363  Pgr_base_graph< DirectedGraph > digraph(gType, initial_size);
364  Pgr_base_graph< UndirectedGraph > undigraph(gType, initial_size);
365 
366  if (directedFlag) {
367  process(digraph, data_edges, rec_count);
368  } else {
369  process(undigraph, data_edges, rec_count);
370  }
371 
372 }
373 
374 
int process_command_line(po::variables_map &vm, po::options_description &od_desc)
double reverse_cost
Definition: pgr_types.h:146
int64_t source
Definition: pgr_types.h:143
int64_t target
Definition: pgr_types.h:144
void import_from_file(const std::string &input_file_name, pgr_edge_t *edges, unsigned int *count, int64_t start_vertex, int64_t end_vertex, bool &found)
static int conn(int *SPIcode)
Definition: VRP.c:395
void process_dijkstra(G &graph, const std::vector< std::string > &tokens)
Definition: dijkstra.hpp:29
int64_t id
Definition: pgr_types.h:142
double cost
Definition: pgr_types.h:145
int main(int ac, char *av[])
static void exit_nicely(PGconn *conn)
edge_astar_t * edges
Definition: BDATester.cpp:46
graphType
Definition: pgr_types.h:222
void get_options_description(po::options_description &od_desc)
void process(G graph, pgr_edge_t *data_edges, int row_count)