timetables.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*!
  2. \file vector/neta/timetables.c
  3. \brief Network Analysis library - timetables
  4. Shortest path using timetables.
  5. (C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Daniel Bundala (Google Summer of Code 2009)
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <grass/gis.h>
  13. #include <grass/vector.h>
  14. #include <grass/dbmi.h>
  15. #include <grass/glocale.h>
  16. #include <grass/dgl/graph.h>
  17. #include <grass/neta.h>
  18. /*!
  19. \brief Get number of distinct elements
  20. \param driver DB driver
  21. \param sql SQl string
  22. \param[out] list of lengths
  23. \param[out] list of ids
  24. \return number of distinct elements
  25. \return -1 on failure
  26. */
  27. int NetA_init_distinct(dbDriver * driver, dbString * sql, int **lengths,
  28. int **ids)
  29. {
  30. int count, last, cur, result, index, more;
  31. dbCursor cursor;
  32. dbTable *table;
  33. dbColumn *column;
  34. dbValue *value;
  35. if (db_open_select_cursor(driver, sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
  36. G_warning(_("Unable to open select cursor: %s"), db_get_string(sql));
  37. return -1;
  38. }
  39. /*TODO: check column types */
  40. count = last = 0;
  41. /*count number of distinct routes */
  42. table = db_get_cursor_table(&cursor);
  43. column = db_get_table_column(table, 0);
  44. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  45. value = db_get_column_value(column);
  46. cur = db_get_value_int(value);
  47. if (count == 0 || cur != last) {
  48. last = cur;
  49. count++;
  50. }
  51. }
  52. result = count;
  53. db_close_cursor(&cursor);
  54. *lengths = (int *)G_calloc(count, sizeof(int));
  55. *ids = (int *)G_calloc(count, sizeof(int));
  56. if (!*lengths || !*ids) {
  57. G_warning(_("Out of memory"));
  58. return -1;
  59. }
  60. db_open_select_cursor(driver, sql, &cursor, DB_SEQUENTIAL);
  61. count = index = 0;
  62. /*calculate the lengths of the routes */
  63. table = db_get_cursor_table(&cursor);
  64. column = db_get_table_column(table, 0);
  65. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  66. value = db_get_column_value(column);
  67. cur = db_get_value_int(value);
  68. if (count != 0 && cur != last)
  69. index++;
  70. if (count == 0 || cur != last)
  71. (*ids)[index] = cur;
  72. (*lengths)[index]++;
  73. last = cur;
  74. count++;
  75. }
  76. return result;
  77. }
  78. static int cmp_int(const void *a, const void *b)
  79. {
  80. return *(int *)a - *(int *)b;
  81. }
  82. /*!
  83. \brief Initialises timetable from a database
  84. \param In pointer to Map_info structure
  85. \param route_layer layer number of routes
  86. \param walk_layer layer number of walkers
  87. \param route_id id of route
  88. \param times list of timestamps
  89. \param to_stop ?
  90. \param walk_length walk length as string
  91. \param timetable pointer to neta_timetable
  92. \param route_ids list of route ids
  93. \param stop_ids lits of stop ids
  94. \return 0 on success
  95. \return non-zero value on failure
  96. */
  97. int NetA_init_timetable_from_db(struct Map_info *In, int route_layer,
  98. int walk_layer, char *route_id, char *times,
  99. char *to_stop, char *walk_length,
  100. neta_timetable * timetable, int **route_ids,
  101. int **stop_ids)
  102. {
  103. int more, i, stop, route, time, *stop_pnt, stop1, stop2;
  104. dbString sql;
  105. dbCursor cursor;
  106. dbTable *table;
  107. dbColumn *column1, *column2, *column3;
  108. dbValue *value;
  109. char buf[2000];
  110. dbDriver *driver;
  111. struct field_info *Fi;
  112. Fi = Vect_get_field(In, route_layer);
  113. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  114. if (driver == NULL)
  115. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  116. Fi->database, Fi->driver);
  117. db_init_string(&sql);
  118. sprintf(buf, "select %s from %s order by %s", route_id, Fi->table,
  119. route_id);
  120. db_set_string(&sql, buf);
  121. timetable->routes =
  122. NetA_init_distinct(driver, &sql, &(timetable->route_length),
  123. route_ids);
  124. if (timetable->routes < 0)
  125. return 1;
  126. sprintf(buf, "select %s from %s order by %s", Fi->key, Fi->table,
  127. Fi->key);
  128. db_set_string(&sql, buf);
  129. timetable->stops =
  130. NetA_init_distinct(driver, &sql, &(timetable->stop_length), stop_ids);
  131. if (timetable->stops < 0)
  132. return 1;
  133. timetable->route_stops =
  134. (int **)G_calloc(timetable->routes, sizeof(int *));
  135. timetable->route_times =
  136. (int **)G_calloc(timetable->routes, sizeof(int *));
  137. timetable->stop_routes =
  138. (int **)G_calloc(timetable->stops, sizeof(int *));
  139. timetable->stop_times = (int **)G_calloc(timetable->stops, sizeof(int *));
  140. timetable->walk_length = (int *)G_calloc(timetable->stops, sizeof(int));
  141. timetable->walk_stops = (int **)G_calloc(timetable->stops, sizeof(int *));
  142. timetable->walk_times = (int **)G_calloc(timetable->stops, sizeof(int *));
  143. if (!timetable->route_stops || !timetable->route_times ||
  144. !timetable->stop_routes || !timetable->stop_times ||
  145. !timetable->walk_length) {
  146. G_warning(_("Out of memory"));
  147. return 2;
  148. }
  149. for (i = 0; i < timetable->routes; i++) {
  150. timetable->route_stops[i] =
  151. (int *)G_calloc(timetable->route_length[i], sizeof(int));
  152. timetable->route_times[i] =
  153. (int *)G_calloc(timetable->route_length[i], sizeof(int));
  154. if (!timetable->route_stops[i] || !timetable->route_times[i]) {
  155. G_warning(_("Out of memory"));
  156. return 2;
  157. }
  158. timetable->route_length[i] = 0;
  159. }
  160. for (i = 0; i < timetable->stops; i++) {
  161. timetable->stop_routes[i] =
  162. (int *)G_calloc(timetable->stop_length[i], sizeof(int));
  163. timetable->stop_times[i] =
  164. (int *)G_calloc(timetable->stop_length[i], sizeof(int));
  165. if (!timetable->stop_routes[i] || !timetable->stop_times[i]) {
  166. G_warning(_("Out of memory"));
  167. return 2;
  168. }
  169. timetable->walk_length[i] = 0;
  170. timetable->stop_length[i] = 0;
  171. }
  172. sprintf(buf, "select %s, %s, %s from %s order by %s", Fi->key, route_id,
  173. times, Fi->table, times);
  174. db_set_string(&sql, buf);
  175. if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
  176. G_warning(_("Unable to open select cursor: %s"), db_get_string(&sql));
  177. return 1;
  178. }
  179. table = db_get_cursor_table(&cursor);
  180. column1 = db_get_table_column(table, 0);
  181. column2 = db_get_table_column(table, 1);
  182. column3 = db_get_table_column(table, 2);
  183. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  184. value = db_get_column_value(column1);
  185. stop = db_get_value_int(value);
  186. value = db_get_column_value(column2);
  187. route = db_get_value_int(value);
  188. value = db_get_column_value(column3);
  189. time = db_get_value_int(value);
  190. stop =
  191. (int *)bsearch(&stop, *stop_ids, timetable->stops, sizeof(int),
  192. cmp_int) - (*stop_ids);
  193. route =
  194. (int *)bsearch(&route, *route_ids, timetable->routes, sizeof(int),
  195. cmp_int) - (*route_ids);
  196. timetable->stop_routes[stop][timetable->stop_length[stop]] = route;
  197. timetable->stop_times[stop][timetable->stop_length[stop]++] = time;
  198. timetable->route_stops[route][timetable->route_length[route]] = stop;
  199. timetable->route_times[route][timetable->route_length[route]++] =
  200. time;
  201. }
  202. db_close_cursor(&cursor);
  203. if (walk_layer != -1) {
  204. Fi = Vect_get_field(In, walk_layer);
  205. sprintf(buf, "select %s, %s, %s from %s", Fi->key, to_stop,
  206. walk_length, Fi->table);
  207. db_set_string(&sql, buf);
  208. if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
  209. DB_OK) {
  210. G_warning(_("Unable to open select cursor: %s"),
  211. db_get_string(&sql));
  212. return 1;
  213. }
  214. table = db_get_cursor_table(&cursor);
  215. column1 = db_get_table_column(table, 0);
  216. column2 = db_get_table_column(table, 1);
  217. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  218. value = db_get_column_value(column2);
  219. stop = db_get_value_int(value);
  220. stop_pnt =
  221. (int *)bsearch(&stop, *stop_ids, timetable->stops,
  222. sizeof(int), cmp_int);
  223. if (stop_pnt) {
  224. value = db_get_column_value(column1);
  225. stop = db_get_value_int(value);
  226. stop_pnt =
  227. (int *)bsearch(&stop, *stop_ids, timetable->stops,
  228. sizeof(int), cmp_int);
  229. if (stop_pnt) {
  230. stop = stop_pnt - (*stop_ids);
  231. timetable->walk_length[stop]++;
  232. }
  233. }
  234. }
  235. db_close_cursor(&cursor);
  236. for (i = 0; i < timetable->stops; i++) {
  237. timetable->walk_stops[i] =
  238. (int *)G_calloc(timetable->walk_length[i], sizeof(int));
  239. timetable->walk_times[i] =
  240. (int *)G_calloc(timetable->walk_length[i], sizeof(int));
  241. if (!timetable->walk_stops[i] || !timetable->walk_times[i]) {
  242. G_warning(_("Out of memory"));
  243. return 2;
  244. }
  245. timetable->walk_length[i] = 0;
  246. }
  247. if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
  248. DB_OK) {
  249. G_warning(_("Unable to open select cursor: %s"),
  250. db_get_string(&sql));
  251. return 1;
  252. }
  253. table = db_get_cursor_table(&cursor);
  254. column1 = db_get_table_column(table, 0);
  255. column2 = db_get_table_column(table, 1);
  256. column3 = db_get_table_column(table, 2);
  257. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  258. value = db_get_column_value(column2);
  259. stop = db_get_value_int(value);
  260. stop_pnt =
  261. (int *)bsearch(&stop, *stop_ids, timetable->stops,
  262. sizeof(int), cmp_int);
  263. if (stop_pnt) {
  264. stop2 = stop_pnt - (*stop_ids);
  265. value = db_get_column_value(column1);
  266. stop = db_get_value_int(value);
  267. stop_pnt =
  268. (int *)bsearch(&stop, *stop_ids, timetable->stops,
  269. sizeof(int), cmp_int);
  270. if (stop_pnt) {
  271. stop1 = stop_pnt - (*stop_ids);
  272. value = db_get_column_value(column3);
  273. time = db_get_value_int(value);
  274. timetable->walk_stops[stop1][timetable->
  275. walk_length[stop1]] = stop2;
  276. timetable->walk_times[stop1][timetable->
  277. walk_length[stop1]++] = time;
  278. }
  279. }
  280. }
  281. db_close_cursor(&cursor);
  282. }
  283. db_close_database_shutdown_driver(driver);
  284. return 0;
  285. }
  286. typedef struct
  287. {
  288. int v;
  289. int conns;
  290. } neta_heap_data;
  291. static neta_heap_data *new_heap_data(int conns, int v)
  292. {
  293. neta_heap_data *d =
  294. (neta_heap_data *) G_calloc(1, sizeof(neta_heap_data));
  295. d->v = v;
  296. d->conns = conns;
  297. return d;
  298. }
  299. /*!
  300. \brief Update Dijkstra structures
  301. \param olc_conns old connection
  302. \param new_conns new connection
  303. \param to old 'to' node
  304. \param new_dst new 'to' node
  305. \param v ?
  306. \param route id of route
  307. \param rows ?
  308. \param update ?
  309. \param[out] result pointer to neta_timetable_result structure
  310. \param heap ?
  311. */
  312. void NetA_update_dijkstra(int old_conns, int new_conns, int to, int new_dst,
  313. int v, int route, int rows, int update,
  314. neta_timetable_result * result, dglHeap_s * heap)
  315. {
  316. if (result->dst[new_conns][to] == -1 ||
  317. result->dst[new_conns][to] > new_dst) {
  318. result->dst[new_conns][to] = new_dst;
  319. result->prev_stop[new_conns][to] = v;
  320. result->prev_route[new_conns][to] = route;
  321. result->prev_conn[new_conns][to] = old_conns;
  322. if (update) {
  323. dglHeapData_u heap_data;
  324. heap_data.pv = (void *)new_heap_data(new_conns, to);
  325. dglHeapInsertMin(heap, new_dst, ' ', heap_data);
  326. }
  327. }
  328. }
  329. /*!
  330. \brief Computes the earliest arrival time.
  331. Computes the earliest arrival time to to_stop from from_stop
  332. starting at start_time, or -1 if no path exists
  333. \param timetable pointer to neta_timetable structure
  334. \param from_stop 'from' node
  335. \param to_stop 'to' stop
  336. \param start_time start timestamp
  337. \param min_change ?
  338. \param max_changes ?
  339. \param walking_change ?
  340. \param[out] result pointer to neta_timetable_result
  341. \return ?
  342. \return -1 on error
  343. */
  344. int NetA_timetable_shortest_path(neta_timetable * timetable, int from_stop,
  345. int to_stop, int start_time, int min_change,
  346. int max_changes, int walking_change,
  347. neta_timetable_result * result)
  348. {
  349. int i, j;
  350. dglHeap_s heap;
  351. int opt_conns, rows = 1;
  352. if (max_changes != -1)
  353. rows = max_changes + 2;
  354. result->rows = rows;
  355. result->dst = (int **)G_calloc(rows, sizeof(int *));
  356. result->prev_stop = (int **)G_calloc(rows, sizeof(int *));
  357. result->prev_route = (int **)G_calloc(rows, sizeof(int *));
  358. result->prev_conn = (int **)G_calloc(rows, sizeof(int *));
  359. if (!result->dst || !result->prev_stop || !result->prev_route ||
  360. !result->prev_conn) {
  361. G_warning(_("Out of memory"));
  362. return -1;
  363. }
  364. for (i = 0; i < rows; i++) {
  365. result->dst[i] = (int *)G_calloc(timetable->stops, sizeof(int));
  366. result->prev_stop[i] = (int *)G_calloc(timetable->stops, sizeof(int));
  367. result->prev_route[i] =
  368. (int *)G_calloc(timetable->stops, sizeof(int));
  369. result->prev_conn[i] = (int *)G_calloc(timetable->stops, sizeof(int));
  370. if (!result->dst[i] || !result->prev_stop[i] || !result->prev_route[i]
  371. || !result->prev_conn[i]) {
  372. G_warning(_("Out of memory"));
  373. return -1;
  374. }
  375. }
  376. if (from_stop == to_stop) {
  377. result->dst[0][to_stop] = start_time;
  378. result->prev_route[0][to_stop] = result->prev_stop[0][to_stop] = -1;
  379. result->routes = 0;
  380. return start_time;
  381. }
  382. result->routes = -1;
  383. if (walking_change > 1)
  384. walking_change = 1;
  385. if (walking_change < 0 || max_changes == -1)
  386. walking_change = 0;
  387. dglHeapInit(&heap);
  388. for (i = 0; i < rows; i++)
  389. for (j = 0; j < timetable->stops; j++)
  390. result->dst[i][j] = result->prev_stop[i][j] =
  391. result->prev_route[i][j] = -1;
  392. result->dst[0][from_stop] = start_time - min_change;
  393. result->prev_stop[0][from_stop] = result->prev_route[0][from_stop] = -1;
  394. dglHeapData_u heap_data;
  395. heap_data.pv = (void *)new_heap_data(0, from_stop);
  396. dglHeapInsertMin(&heap, start_time - min_change, ' ', heap_data);
  397. while (1) {
  398. dglInt32_t v, dist, conns;
  399. dglHeapNode_s heap_node;
  400. int new_conns, walk_conns, update;
  401. if (!dglHeapExtractMin(&heap, &heap_node))
  402. break;
  403. v = ((neta_heap_data *) (heap_node.value.pv))->v;
  404. conns = ((neta_heap_data *) (heap_node.value.pv))->conns;
  405. dist = heap_node.key;
  406. if (dist > result->dst[conns][v])
  407. continue;
  408. if (v == to_stop)
  409. break;
  410. new_conns = (max_changes == -1) ? 0 : (conns + 1);
  411. walk_conns = conns + walking_change;
  412. /*walking */
  413. if (walk_conns < rows) {
  414. /* update = (max_changes == -1 || walk_conns <= max_changes); */
  415. update = 1;
  416. for (i = 0; i < timetable->walk_length[v]; i++) {
  417. int to = timetable->walk_stops[v][i];
  418. int new_dst = dist + timetable->walk_times[v][i];
  419. NetA_update_dijkstra(conns, walk_conns, to, new_dst, v, -2,
  420. rows, update, result, &heap);
  421. }
  422. }
  423. if (new_conns >= rows)
  424. continue;
  425. /*process all routes arriving after dist+min_change */
  426. for (i = 0; i < timetable->stop_length[v]; i++)
  427. if (timetable->stop_times[v][i] >= dist + min_change) {
  428. int route = timetable->stop_routes[v][i];
  429. /*find the index of v on the route */
  430. for (j = 0; j < timetable->route_length[route]; j++)
  431. if (timetable->route_stops[route][j] == v)
  432. break;
  433. j++;
  434. for (; j < timetable->route_length[route]; j++) {
  435. int to = timetable->route_stops[route][j];
  436. NetA_update_dijkstra(conns, new_conns, to,
  437. timetable->route_times[route][j], v,
  438. route, rows, 1, result, &heap);
  439. }
  440. }
  441. }
  442. dglHeapFree(&heap, NULL);
  443. opt_conns = -1;
  444. for (i = 0; i < rows; i++)
  445. if (result->dst[i][to_stop] != -1 &&
  446. (opt_conns == -1 ||
  447. result->dst[opt_conns][to_stop] > result->dst[i][to_stop]))
  448. opt_conns = i;
  449. result->routes = opt_conns;
  450. if (opt_conns != -1)
  451. return result->dst[opt_conns][to_stop];
  452. return -1;
  453. }
  454. /*!
  455. \brief Get time
  456. Get time when route "route" arrives at stop "stop" or -1.
  457. \param timetable pointer to neta_timetable structure
  458. \param stop 'stop' node id
  459. \param route route id
  460. \return time
  461. \return -1 if not found
  462. */
  463. int NetA_timetable_get_route_time(neta_timetable * timetable, int stop,
  464. int route)
  465. {
  466. int i;
  467. for (i = 0; i < timetable->route_length[route]; i++)
  468. if (timetable->route_stops[route][i] == stop)
  469. return timetable->route_times[route][i];
  470. return -1;
  471. }
  472. /*!
  473. \brief Free neta_timetable_result structure
  474. \param result pointer to neta_timetable_result structure
  475. */
  476. void NetA_timetable_result_release(neta_timetable_result * result)
  477. {
  478. int i;
  479. for (i = 0; i < result->rows; i++) {
  480. G_free(result->dst[i]);
  481. G_free(result->prev_stop[i]);
  482. G_free(result->prev_route[i]);
  483. }
  484. G_free(result->dst);
  485. G_free(result->prev_stop);
  486. G_free(result->prev_route);
  487. }