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