PGROUTING  3.2
basePath_SSEC.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: basePath_SSEC.cpp
3 
4 Copyright (c) 2015 Celia Virginia Vergara Castillo
6 
7 ------
8 
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23  ********************************************************************PGR-GNU*/
24 
26 
27 #include <cmath>
28 #include <limits>
29 #include <deque>
30 #include <iostream>
31 #include <algorithm>
32 #include <utility>
33 
35 #include "cpp_common/pgr_assert.h"
36 
37 
38 Path& Path::renumber_vertices(int64_t value) {
39  for (auto &r : path) {
40  r.node += value;
41  }
42  m_start_id += value;
43  m_end_id += value;
44  return *this;
45 }
46 
48  path.push_front(data);
49  m_tot_cost += data.cost;
50 }
51 
52 void Path::push_back(Path_t data) {
53  path.push_back(data);
54  m_tot_cost += data.cost;
55 }
56 
57 void Path::reverse() {
58  std::swap(m_start_id, m_end_id);
59  if (path.size() <= 1) return;
60  std::deque< Path_t > newpath;
61  for (size_t i = 0; i < path.size(); ++i) {
62  newpath.push_front({
63  path[i].node,
64  (i == 0? -1 : path[i - 1].edge),
65  (i == 0? 0 : path[i - 1].cost),
66  0
67  });
68  }
69  for (size_t i = 0; i < newpath.size(); ++i) {
70  newpath[i].agg_cost = (i == 0)?
71  0 :
72  newpath[i - 1].agg_cost + newpath[i - 1].cost;
73  }
74  path = newpath;
75 }
76 
78  m_tot_cost = 0;
79  for (auto &p : path) {
80  p.agg_cost = m_tot_cost;
81  m_tot_cost += p.cost;
82  }
83 }
84 
85 
86 
87 void Path::clear() {
88  path.clear();
89  m_tot_cost = 0;
90  m_start_id = 0;
91  m_end_id = 0;
92 }
93 
95  const pgrouting::trsp::Rule &rule) const {
96  return std::search(path.begin(), path.end(), rule.begin(), rule.end(),
97  [](Path_t p, int64_t e) {return p.edge == e;});
98 }
99 
101  const pgrouting::trsp::Rule &rule) const {
102  return find_restriction(rule) != path.end();
103 }
104 
106  const pgrouting::trsp::Rule &rule) {
107  auto position = std::search(
108  path.begin(), path.end(), rule.begin(), rule.end(),
109  [](Path_t p, int64_t e) { return p.edge == e;});
110  if (position != path.end()) {
111  position->agg_cost = std::numeric_limits<double>::infinity();
112  }
113  return *this;
114 }
115 
116 
117 
118 std::ostream& operator<<(std::ostream &log, const Path &path) {
119  log << "Path: " << path.start_id() << " -> " << path.end_id() << "\n"
120  << "seq\tnode\tedge\tcost\tagg_cost\n";
121  int64_t i = 0;
122  for (const auto &e : path) {
123  log << i << "\t"
124  << e.node << "\t"
125  << e.edge << "\t"
126  << e.cost << "\t"
127  << e.agg_cost << "\n";
128  ++i;
129  }
130  return log;
131 }
132 
133 size_t Path::countInfinityCost() const {
134  return static_cast<size_t>(std::count_if(path.begin(), path.end(),
135  [](Path_t const&p) -> size_t {
136  return std::isinf(p.agg_cost);
137  }));
138 }
139 
140 
141 Path Path::getSubpath(unsigned int j) const {
142  Path result(start_id(), end_id());
143  if (j == 0) return result;
144  for (auto i = path.begin(); i != path.begin() + j; ++i) {
145  result.push_back((*i));
146  }
147  pgassert(result.tot_cost() != 0);
148  pgassert(this->tot_cost() != 0);
149  return result;
150 }
151 
152 
153 bool Path::isEqual(const Path &subpath) const {
154  if (subpath.empty()) return true;
155  if (subpath.size() >= path.size()) return false;
156  std::deque< Path_t >::const_iterator i, j;
157  for (i = path.begin(), j = subpath.begin();
158  j != subpath.end();
159  ++i, ++j)
160  if ((*i).node != (*j).node) return false;
161  return true;
162 }
163 
164 void Path::appendPath(const Path &o_path) {
165  path.insert(path.end(), o_path.path.begin(), o_path.path.end());
167 }
168 
169 
192 void Path::append(const Path &other) {
193  pgassert(m_end_id == other.m_start_id);
194  if (other.m_start_id == other.m_end_id) {
195  pgassert(other.path.empty());
196  return;
197  }
198  if (m_start_id == m_end_id) {
199  pgassert(path.empty());
200  *this = other;
201  return;
202  }
203 #if 0
204  pgassert(path.back().cost == 0);
205 #endif
206  pgassert(path.back().edge == -1);
207  m_end_id = other.m_end_id;
208 
209  auto last = path.back();
210  auto agg_cost = last.agg_cost;
211 
212  path.pop_back();
213 
214  for (auto item : other.path) {
215  item.agg_cost += agg_cost;
216  push_back(item);
217  }
218 }
219 
220 
222  General_path_element_t **postgres_data,
223  size_t &sequence) const {
224  int i = 1;
225  for (const auto e : path) {
226  auto agg_cost = std::fabs(
227  e.agg_cost - (std::numeric_limits<double>::max)()) < 1?
228  std::numeric_limits<double>::infinity() : e.agg_cost;
229  auto cost = std::fabs(e.cost - (std::numeric_limits<double>::max)()) < 1?
230  std::numeric_limits<double>::infinity() : e.cost;
231 
232  (*postgres_data)[sequence] = {i, start_id(), end_id(), e.node, e.edge, cost, agg_cost};
233  ++i;
234  ++sequence;
235  }
236 }
237 
238 /* used by driving distance */
240  General_path_element_t **ret_path,
241  size_t &sequence) const {
242  for (unsigned int i = 0; i < path.size(); i++) {
243  (*ret_path)[sequence].seq = static_cast<int>(i);
244  (*ret_path)[sequence].start_id = start_id();
245  (*ret_path)[sequence].end_id = start_id();
246  (*ret_path)[sequence].node = path[i].node;
247  (*ret_path)[sequence].edge = path[i].edge;
248  (*ret_path)[sequence].cost = path[i].cost;
249  (*ret_path)[sequence].agg_cost = path[i].agg_cost;
250  sequence++;
251  }
252 }
253 
254 /* used by ksp */
256  General_path_element_t **ret_path,
257  size_t &sequence, int routeId) const {
258  for (unsigned int i = 0; i < path.size(); i++) {
259  (*ret_path)[sequence].seq = static_cast<int>(i + 1);
260  (*ret_path)[sequence].start_id = routeId;
261  (*ret_path)[sequence].end_id = end_id();
262  (*ret_path)[sequence].node = path[i].node;
263  (*ret_path)[sequence].edge = path[i].edge;
264  (*ret_path)[sequence].cost = path[i].cost;
265  (*ret_path)[sequence].agg_cost = (i == 0)?
266  0 :
267  (*ret_path)[sequence-1].agg_cost + path[i-1].cost;
268  sequence++;
269  }
270 }
271 
272 /* used by turn restricted */
274  General_path_element_t **ret_path,
275  size_t &sequence, int routeId) const {
276  for (unsigned int i = 0; i < path.size(); i++) {
277  (*ret_path)[sequence].seq = static_cast<int>(i + 1);
278  (*ret_path)[sequence].start_id = routeId;
279  (*ret_path)[sequence].end_id = end_id();
280  (*ret_path)[sequence].node = path[i].node;
281  (*ret_path)[sequence].edge = path[i].edge;
282  (*ret_path)[sequence].cost = path[i].cost;
283  (*ret_path)[sequence].agg_cost = path[i].agg_cost;
284  sequence++;
285  }
286 }
287 
288 
294 void
296  std::sort(path.begin(), path.end(),
297  [](const Path_t &l, const Path_t &r)
298  {return l.node < r.node;});
299  std::stable_sort(path.begin(), path.end(),
300  [](const Path_t &l, const Path_t &r)
301  {return l.agg_cost < r.agg_cost;});
302 }
303 
304 /*
305  * FRIENDS
306  */
307 
308 
309 size_t
311  General_path_element_t **ret_path,
312  const std::deque< Path > &paths) {
313  size_t sequence = 0;
314  for (const Path &path : paths) {
315  if (path.path.size() > 0)
316  path.generate_postgres_data(ret_path, sequence);
317  }
318  return sequence;
319 }
320 
321 /*
322  * sort the paths by size from greater to smaller
323  * and sort each path by node
324  * all the nodes on p2 are going to be compared
325  * with the nodes of p1
326  *
327  * When both paths reach the node and p1.agg_cost > p2.agg_cost
328  * erase the node of p1
329  * (can't erase from p2 because we loose the iterators
330  * so in a future cycle it will be deleted)
331  *
332  * sort the paths by start_id,
333  */
334 
335 void
336 equi_cost(std::deque< Path > &paths) {
337  /* sort paths by size: largest first */
338  std::sort(paths.begin(), paths.end(),
339  [](const Path &e1, const Path &e2)->bool {
340  return e2.size() < e1.size();
341  });
342 
343  /* sort each path by node: smaller id first */
344  for (auto &p : paths) {
345  if (p.size() < 2) continue;
346  std::sort(p.begin(), p.end(),
347  [](const Path_t &e1, const Path_t &e2)->bool {
348  return e1.node < e2.node;
349  });
350  }
351 
352  for (auto &p1 : paths) {
353  for (const auto &p2 : paths) {
354  if (p1.start_id() == p2.start_id()) continue;
355  for (const auto &stop : p2.path) {
356  /* find the node of p2 in p1 */
357  auto pos = lower_bound(p1.begin(), p1.end(), stop,
358  [](const Path_t &l, const Path_t &r)->bool {
359  return l.node < r.node;
360  });
361 
362  if (pos != p1.end()
363  && (stop.node == pos->node)
364  && (stop.agg_cost < pos->agg_cost)) {
365  /* both share the same node &
366  * the second path has the smallest
367  * So erasing from the first path */
368  p1.erase(pos);
369  }
370  }
371  }
372  }
373  /* sort paths by start_id */
374  std::sort(paths.begin(), paths.end(),
375  [](const Path &e1, const Path &e2)->bool {
376  return e1.start_id() < e2.start_id();
377  });
378 
379  /* sort each path by agg_cost, node */
380  for (auto &path : paths) {
381  path.sort_by_node_agg_cost();
382  }
383 }
384 
385 
386 size_t
387 count_tuples(const std::deque< Path > &paths) {
388  size_t count(0);
389  for (const Path &e : paths) {
390  count += e.path.size();
391  }
392  return count;
393 }
Path::end_id
int64_t end_id() const
Definition: basePath_SSEC.hpp:67
Path
Definition: basePath_SSEC.hpp:47
Path::path
std::deque< Path_t > path
Definition: basePath_SSEC.hpp:52
Path::start_id
int64_t start_id() const
Definition: basePath_SSEC.hpp:65
Path::inf_cost_on_restriction
Path inf_cost_on_restriction(const pgrouting::trsp::Rule &rule)
Definition: basePath_SSEC.cpp:105
Path::push_back
void push_back(Path_t data)
Definition: basePath_SSEC.cpp:52
count_tuples
size_t count_tuples(const std::deque< Path > &paths)
Definition: basePath_SSEC.cpp:387
Path_t
Definition: path_t.h:36
Path::end
pthIt end()
Definition: basePath_SSEC.hpp:82
Path::countInfinityCost
size_t countInfinityCost() const
Definition: basePath_SSEC.cpp:133
Path::reverse
void reverse()
Definition: basePath_SSEC.cpp:57
Path::empty
bool empty() const
Definition: basePath_SSEC.hpp:72
Path::getSubpath
Path getSubpath(unsigned int j) const
Definition: basePath_SSEC.cpp:141
collapse_paths
size_t collapse_paths(General_path_element_t **ret_path, const std::deque< Path > &paths)
Definition: basePath_SSEC.cpp:310
pgrouting::trsp::Rule
Definition: rule.h:39
Path::push_front
void push_front(Path_t data)
Definition: basePath_SSEC.cpp:47
Path::appendPath
void appendPath(const Path &o_path)
Definition: basePath_SSEC.cpp:164
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:94
equi_cost
void equi_cost(std::deque< Path > &paths)
Definition: basePath_SSEC.cpp:336
Path::has_restriction
bool has_restriction(const pgrouting::trsp::Rule &rule) const
Definition: basePath_SSEC.cpp:100
Path::m_end_id
int64_t m_end_id
Definition: basePath_SSEC.hpp:54
Path::sort_by_node_agg_cost
void sort_by_node_agg_cost()
Sorts a path by node, aggcost ascending.
Definition: basePath_SSEC.cpp:295
pgr_assert.h
An assert functionality that uses C++ throw().
Path::get_pg_dd_path
void get_pg_dd_path(General_path_element_t **ret_path, size_t &sequence) const
Definition: basePath_SSEC.cpp:239
Path::get_pg_ksp_path
void get_pg_ksp_path(General_path_element_t **ret_path, size_t &sequence, int routeId) const
Definition: basePath_SSEC.cpp:255
Path::ConstpthIt
std::deque< Path_t >::const_iterator ConstpthIt
Definition: basePath_SSEC.hpp:49
General_path_element_t
Definition: general_path_element_t.h:37
Path::size
size_t size() const
Definition: basePath_SSEC.hpp:71
Path::generate_postgres_data
void generate_postgres_data(General_path_element_t **postgres_data, size_t &sequence) const
Definition: basePath_SSEC.cpp:221
Path::m_tot_cost
double m_tot_cost
Definition: basePath_SSEC.hpp:55
Path::m_start_id
int64_t m_start_id
Definition: basePath_SSEC.hpp:53
general_path_element_t.h
pgrouting::trsp::Rule::begin
constiterator begin() const
Definition: rule.h:52
operator<<
std::ostream & operator<<(std::ostream &log, const Path &path)
Definition: basePath_SSEC.cpp:118
Path::get_pg_turn_restricted_path
void get_pg_turn_restricted_path(General_path_element_t **ret_path, size_t &sequence, int routeId) const
Definition: basePath_SSEC.cpp:273
pgrouting::trsp::Rule::end
constiterator end() const
Definition: rule.h:53
Path::append
void append(const Path &other)
Path: 2 -> 9 seq node edge cost agg_cost 0 2 4 1 0 1 5 8 1 1 2 6 9 1 2 3 9 -1 0 3 Path: 9 -> 3 seq no...
Definition: basePath_SSEC.cpp:192
Path::renumber_vertices
Path & renumber_vertices(int64_t value)
Definition: basePath_SSEC.cpp:38
Path::begin
pthIt begin()
Definition: basePath_SSEC.hpp:81
Path::isEqual
bool isEqual(const Path &subpath) const
Definition: basePath_SSEC.cpp:153
Path::recalculate_agg_cost
void recalculate_agg_cost()
Definition: basePath_SSEC.cpp:77
Path_t::cost
double cost
Definition: path_t.h:39
Path::clear
void clear()
Definition: basePath_SSEC.cpp:87
Path::tot_cost
double tot_cost() const
Definition: basePath_SSEC.hpp:69
Path::find_restriction
ConstpthIt find_restriction(const pgrouting::trsp::Rule &rule) const
get the iterator of the path where the (restriction) rule starts
Definition: basePath_SSEC.cpp:94
basePath_SSEC.hpp