- Join over
**1.5M+ people** - Join over
**100K+ communities** - Free
**without limits** - Create
**your own community**

- Sep 17 05:43dkastl closed #1611
- Sep 17 05:43dkastl commented #1611
- Sep 16 13:34ohadmanor commented #1611
- Sep 16 01:56dkastl commented #1611
- Sep 15 12:44ohadmanor labeled #1611
- Sep 15 12:44ohadmanor opened #1611
- Sep 14 23:09dkastl synchronize #1573
- Sep 14 02:09dkastl commented #1610
- Sep 14 02:09dkastl commented #1610
- Sep 14 02:04cvvergara commented #1610
- Sep 14 02:01dkastl commented #1610
- Sep 14 01:49cvvergara commented #1610
- Sep 14 01:42cvvergara commented #1610
- Sep 14 01:37dkastl commented #1610
- Sep 03 05:18dkastl milestoned #1610
- Sep 03 05:18dkastl labeled #1610
- Sep 03 05:18dkastl labeled #1610
- Sep 03 05:18dkastl labeled #1610
- Sep 03 05:18dkastl opened #1610
- Aug 24 21:41
cvvergara on develop

Removed the links from linkchec… (compare)

@cvvergara If edge

`cost`

is reduced to match the partial travel time, then one can find all the partial edges easily. Edges are found by comparing the cost of the input edges with same `edge`

id and the output edges. This is definitely more elegant than finding the predecessors and checking the `agg_cost`

for the predecessor.
@EPajares So that would be a breaking change, because of the additional lines, but what if have in the signature an optional named parameter (and last on the list of parameters) I am thinking of this possibilities: names can be different of the possibilities I mention but the important thing is that the default value **must give the current results**

`tails`

with default value FALSE- OR
`vertex_ending`

with default TRUE

@cvvergara Yeah, the naming can be related to tree leaves, given that the current result is a spanning tree, this would extend the leaves with partial edges that end at a place between vertices of the real edge.

The implementation of the fix can be made in such a way to keep the current results. What worries me the most is the fact that the fix requires a custom dijkstra implementation and does not use any of the datastructures used by all of the graph algorithms in pgrouting codebase. I'm confident that the code is correct and performs well.

@EPajares and I will do exhaustive testing to see that the examples deemed previously incorrect (without partial edges or `tails`

as you call it) are now fully correct.

The reason why the `pgr_drivingDistance`

function is useful is for finding isochrones. In this case all the nodes at which `agg_cost`

is less than the given `drivingDistance`

are not useful.

Maybe that deserves a new function name?

it finds the nodes where cost from source to node is <= distance

Why are the results incorrect given that definition?

note that we are not finding edges that are within the distance

the results on the edges is a spanning graph, its not a minimum spanning graph, its just a spanning graph.

Why are the results incorrect given that definition?

note that we are not finding edges that are within the distance

the results on the edges is a spanning graph, its not a minimum spanning graph, its just a spanning graph.

The current implementation calculates nodes that are within the distance.

Give me a counter example, an execution, where the nodes are not within the distance.

Note that: A node on the "tail" is not within the distance because its further away than distance. So this is not what I am asking for.

Give me a counter example, an execution, where the nodes are not within the distance.

Note that: A node on the "tail" is not within the distance because its further away than distance. So this is not what I am asking for.

I will be waiting for your tests.

@cvvergara When one wants to find isochrones, then `pgr_drivingDistance`

obviously gives incomplete results. It gives correct results according to the definition but incomplete for a particular use case. @EPajares had many examples where he wanted to find isochrones but was using the `pgr_drivingDistance`

and getting incomplete results. These are the examples that my fix is going to cover.

Given that the interest is in isochrones and not in nodes that are reached in time `<= drivingDistance`

, I asked if the fix maybe deserves a new function name and probably a different result.

At least that's my interpretation of the issue (#584)[pgRouting/pgrouting#584]

@cvvergara and @vjeranc thanks for your discussions on this. I think it is a matter of definition whether the current result of pgr_drivingDistance can be regarded as complete or incomplete. So maybe there is no need for a debate on this. I would say what we are trying to attempt is to make the result more realistic when moving on a street network. I would propose that we could do the implementation for the testing with a new function name while always considering the maximum of compatibility with the current input and output parameters. @cvvergara I will think further about your comments. After the first demonstration testings we could discuss again more closely about further details and the compatibility with the existing function.

@EPajares Just a side note,

One of the biggest issues that pgRouting had when the release 2.0 had was that all the functions were done thinking on real problems, then tests were done with "real" data, and code was adjusted to fit the "real" data.

Even pgr_dijkstra, to test this, download version 2.0 compile it and run a pgr_dijkstra on the sample data for a directed graph from vertex 1 to vertex 3, if you see the sample data graph answer should be (vertex ordering) 1->2->5->6->9->4->3 but version 2.0 returns 1->2->3

pgRouting is about graphs, graphs can be for streets which I think its your "real problem", but can also be for people relationships, electricity distribution, rivers, and so many other kind of data that I can not think of.

But, in the case of driving distance This is the definition we are using:

Using the Dijkstra algorithm, extracts all the nodes that have costs less than or equal to the value distance. The edges extracted will conform to the corresponding spanning tree.

Note that its not the minimum spanning tree its a spanning tree. where the root is the starting vertex.

The important thing here is the statement "extracts all the nodes that have costs less than or equal to the value distance."

So in your testing try to find an example where results are wrong given the definition we are using. (aka it returns a node that is not less than or equal to the value distance)

Thinking of sets, here is a problem

given S = {1,2,3,4,5}

which are the numbers less than 3.2?

Answer: A = {1,2,3}

@cvvergara `pgr_drivingDistance`

behaves as the definition states, there are no examples showing that the behavior is different from the definition.

I believe most users use the OSM heavily discrete graph together with pgrouting.

In this case, many of the reachable points in the continuous world on the network defined by the graph will not be included in the resulting edges. #584 shows one example of a point reachable in the real world but the edge including that point is not in the result.

@EPajares needs these points and `pgr_drivingDistance`

is not complete for his usecase.

Given that his usecase is finding these reachable points where travel time is exactly the given `drivingDistance`

(points that define the isochrones map), we ask if maybe the function implementing this continuous use case deserves a different name or maybe it does not belong in the `pgrouting`

codebase at all.

I am thinking of edge cases: (for simplicity suppose all edges cost is 1 and undirected graph)

E = {e(v1,v2) e(v1,v3) e(v2,v3)} V= {v1,v2,v3}

pgr_drivingDistance results for a distance of 1.2:

The spanning tree is {e(v1,v2) e(v1,v3)}

The vertices within the distance {v1,v2,v3}

The edge in question is e(v2,v3)`v2 ==+------+==v3`

So, get the vertices that are (vertices that are leafs of the tree, 1.2 - agg_cost to get there): {(v2,0.2)(v3,0.2)}

Get the outgoing edges (using postgres queries)

For (v2,0.2): e(v2,v3) (cost is 1 remember)

Then you need 0.2 distance from v2 to v3

For (v2,0.2): e(v2,v3) (cost is 1 remember)

Then you need 0.2 distance from v2 to v3

For (v3,0.2): e(v3,v2) (remember this example is for undirected)

Then you need 0.2 distance from v3 to v2

Then you need 0.2 distance from v3 to v2

if the change is done permanently, the topology needed for routing of the new geometries must be updated accordingly

So because some costs are not 1, I am writing the cost in each edge.

new E = {e(v1,v2,1) e(v1,v3,1) e(v2,v4,0.2) e(v4,v5,0.6), e(v5,v3,0.2)}

new V= {v1,v2,v3,v4,v5}

new E = {e(v1,v2,1) e(v1,v3,1) e(v2,v4,0.2) e(v4,v5,0.6), e(v5,v3,0.2)}

new V= {v1,v2,v3,v4,v5}

`v2 ==v5------v5==v3`

@cvvergara thanks again! You are right we are solely thinking about street networks. I guess there are many other use cases where the behavior of **not including partial edges** is intended. The same is also in the definition you mentioned. In fact I am currently doing the post-processing with pgr_drivingDistance results + PostgreSQL queries + PostGIS functionality as you mentioned but I am unhappy with the performance. So this was actually the reason that I thought it might make sense (at least in my naive world ;) )to directly return the "partial edges" in the pgRouting-function.

I know for performance there might exist other libraries but I wanted to use pgRouting because I am running calculation on extremely varying graphs. So I cannot use contraction hierarchies and managing everything in the DB is very appealing to me. Currently I am running the tests with the implementation of @vjeranc and performance is very good. I need to do more in-depth testing still but at least for my use case this implementation is very useful. But yeah I understand if it might be rejected as new feature because it is too tailored to as single problem.

Regarding the `pgr_drivingDistance`

before I understand the use case and I have also had the one @EPajares describes.

However, as @cvvergara describes correctly the functions is about nodes and not actually edges and according to the definiton it does what it should do.

That said, there is definitely a need for another function, that could for example extend `pgr_drivingDistance`

and might make a lot of people happy. ;-)

However, pgRouting is an Open Source project and so it is some sort of "do-ocracy" and every contribution or pull request will be highly appreciated.

And if that's not the case, most Open Source projects are funded in some way, and so it is the case with pgRouting.

It's not only volunteer time, so whoever needs something, consider to fund the development!

https://funding.communitybridge.org/projects/pgrouting

Back to the `pgr_drivingDistance`

function, it should be possible to

- know all connected edges from the nodes that can be reached
- know the remaining "costs" from that node

So it should be possible to compute, which fraction of each connected edge can be reached with the remaining cost.

It takes a bit of time to develop this function, especially to make it applicable to generic use cases, but in my opinion it's solvable.

There are two approaches (as outlined in the pdf that @EPajares put a while ago https://gitter.im/pgRouting/pgrouting?at=5ed76ad07da67d06faebe5a3). One is to get the leaves using pgr_drivingDistance and then go to all the neighbors of a leaf L by travelling partially on the edges. This means that if someone was following the shortest path and arrived at leaf L then traveling partially on the outgoing edges reaches the drivingDistance limit. This method returns the largest number of edges.

If, on the other hand, we put the partial edges in the priority queue of the dijkstra algorithm then some of these partial edges will be ignored (the edge case described at the bottom of pdf).

It depends on what the user wants.

First approach does not require changes to the algorithm and can be a postprocessing step.

Second approach cannot be achieved without directly controlling the dijkstra search loop.

I implemented the second approach https://github.com/vjeranc/pgrouting (branch partial_isochrones) and backported it to 2.6.3 (main branch). @EPajares is testing this branch.

During development I noticed that my `pgr_isochrones`

function is 2-35x times faster than `pgr_drivingDistance`

. I believe there's unintentional quadratic behavior in the `Path`

data structure. Speed difference increases with the average number of neighbors of each node. I guess you'd definitely want a speed improvement PR (fix in `Path`

).

It took me a while to be able to do some tests (running `pgr_dijkstra`

and using pgrouting data structures against my implementation) with simple executables (without linking to postgres libraries and libpgrouting.so) so maybe a PR reorganizing cmake build so that it's easy to just add executables with CMakeLists.txt can also be the outcome of this endeavour.

@vjeranc , thank you!

And sorry if I missed some conversation before at it seems.

It would be great if this could become a pull request, so it can be part of all distribution packages with the next release for example.

There were probably plenty of changes with the 3.0 release, but if you need sosme help with that, let us know!

And sorry if I missed some conversation before at it seems.

It would be great if this could become a pull request, so it can be part of all distribution packages with the next release for example.

There were probably plenty of changes with the 3.0 release, but if you need sosme help with that, let us know!

purpose make sure detachment of "current real problem" and because the code is not using a Boost function

- Clear statement of the problem to be solved
- Mathematically
- Natural language
- Include the kind of graph it works with
- directed
- undirected
- if it problem is not solvable for one of those kinds, clearly state why

- Discussion of the name to be used when added to pgRouting (will use for sake of simplicity
`pgr_isochrones`

in this topic) - User documentation including automatically generated results of example queries
- pgtap unit tests with different graphs on the created by edges_SQL (E set) where the vertices are deduced from E, +1 node given by the start_vid.
- E = {}
- E has one vertex
- E has 2 vertices and one edge
- second node is reachable from start_vid exactly
- second node is unreachable from start_vid so result is within the lone edge

- E has 3 vertices
- many combinations of possible edges that can exist with 3 vertices
- together with many combinations of reach-ability

- E has 4 vertices
- many combinations of possible edges that can exist with 4 vertices
- together with many combinations of reach-ability

- No server crash test
- Normally happens when data is NULL

- Test of persistence
- equivalence tests, examples:
- if the reached node is a real vertex of the graph, then executing pgr_dijkstra will give the total aggregate cost with the same value returned by the
`pgr_isochrones`

(if so applies) - if the reached node is a node within an edge of the graph,
`virtual vertex`

, (that gives the exact distance used on the call of`pgr_isochrones`

, then executing`pgr_dijkstraWithPoints`

from the start_vid to the`virtual vertex`

will give the total aggregate cost with the same value`distance`

used with the call to`pgr_isochrones`

. (actually this same function can be used when the node is a real vertex on the graph). - see example of equivalence test.

- if the reached node is a real vertex of the graph, then executing pgr_dijkstra will give the total aggregate cost with the same value returned by the

Remember a test is independent from the code, so to design a test first make the graph, write down the expected results.

Example

From this query:

```
SELECT * FROM pgr_isochrones(
'SELECT id, source, target, cost, reverse_cost FROM edge_table WHERE id > 20',
1, 2.5::FLOAT, true);
```

empty results are expected, because the internally generated graph is G=(E={}, V={1}) so the pgtap test would be:

```
SELECT is_empty($$
SELECT * FROM pgr_isochrones(
'SELECT id, source, target, cost, reverse_cost FROM edge_table WHERE id > 20',
1, 2.5::FLOAT, true)
$$);
```

@cvvergara Ma'am in GitHub builds, I am facing this problem: https://github.com/pgRouting/GSoC-pgRouting/pull/43/checks?check_run_id=760255460#step:3:562

```
Ver Cluster Port Status Owner Data directory Log file
9.5 main 5433 down postgres /var/lib/postgresql/9.5/main /var/log/postgresql/postgresql-9.5-main.log
```

Maybe the postgresql on port 5433 is down, so, anything which can be done to fix this, or is it just a GitHub actions problem and we shall just wait for the problem to get resolved?

I got this error in all the commits which I made yesterday; the builds on travis and appveyor are passing.

I tried re-running several times, still the problems isn't resolved.

@rajhim2 Maybe you are still facing the same problem in your pull request in the GSoC-pgRouting repository : pgRouting/GSoC-pgRouting#42

Your build is failing there, though it passed in your forked repository's branch

@cvvergara Ma'am, for the pgTAP unit tests, are we required to use the pgRouting's Sample Data (`edge_table`

) somehow for graphs like 2 vertices + 1 edge, or 3 vertices, or 4 vertices?

Or, for each such graph (3 vertices, 4 vertices etc), we can create a separate table and then use `set_eq`

to match the queries and the results?

@krashish8 , good question.

I would say that if you can reuse the existing sample data for your case, that would be best, because maintaining multiple sample networks is extra work.

If you think the current sample network is not suitable, maybe we can extend it to also cover your use case.

I would say that if you can reuse the existing sample data for your case, that would be best, because maintaining multiple sample networks is extra work.

If you think the current sample network is not suitable, maybe we can extend it to also cover your use case.

Currently the .hpp code is returning incorrect output.

```
SELECT * FROM pgr_boyerMyrvold(
'SELECT id, source, target, cost, reverse_cost
FROM edge_table WHERE id IN (15,8,16,9)'
);
id | source | target | cost | reverse_cost
----+--------+--------+-----------------------+--------------
1 | 8 | 5 | 2.96439387504748e-323 | 1
2 | 9 | 6 | 4.44659081257122e-323 | 1
3 | 15 | 9 | 5.92878775009496e-323 | 1
4 | 16 | 4 | 4.44659081257122e-323 | 1
(4 rows)
```

```
id | source | target | cost | reverse_cost
----+--------+--------+------+--------------
8 | 5 | 6 | 1 | 1
9 | 6 | 9 | 1 | 1
15 | 9 | 12 | 1 | 1
16 | 4 | 9 | 1 | 1
(4 rows)
```

```
Generating html/en documentation ...
Running Sphinx v2.4.0
loading translations [en]... done
loading pickled environment... done
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 0 source files that are out of date
updating environment: 0 added, 0 changed, 0 removed
looking for now-outdated files... none found
no targets are out of date.
build succeeded.
The HTML pages are in html/en.
Built target html-en
Built target html
Built target doc
[100%] Generating API documentation with Doxygen
Error: /home/himanshu/GSoC-pgRouting/build/doxygen/html/inline_dotgraph_2.dot: syntax error in line 14 near '-'
Error: /home/himanshu/GSoC-pgRouting/build/doxygen/html/inline_dotgraph_2.dot: syntax error in line 14 near '-'
Error: /home/himanshu/GSoC-pgRouting/build/doxygen/latex/inline_dotgraph_2.dot: syntax error in line 14 near '-'
Segmentation fault (core dumped)
doxygen/CMakeFiles/doxy.dir/build.make:57: recipe for target 'doxygen/CMakeFiles/doxy' failed
make[3]: *** [doxygen/CMakeFiles/doxy] Error 139
CMakeFiles/Makefile2:2563: recipe for target 'doxygen/CMakeFiles/doxy.dir/all' failed
make[2]: *** [doxygen/CMakeFiles/doxy.dir/all] Error 2
CMakeFiles/Makefile2:2570: recipe for target 'doxygen/CMakeFiles/doxy.dir/rule' failed
make[1]: *** [doxygen/CMakeFiles/doxy.dir/rule] Error 2
Makefile:593: recipe for target 'doxy' failed
make: *** [doxy] Error 2
```

This doxygen error comes at the step : Generating API documentation with Doxygen. I have installed doxygen and graphviz and pygraphviz correctly. Can anyone please explain.

Since we have an edge representation of the graph, the best I can try was to represent the graph in the following way:

For one isolated vertex:

```
id | source | target | cost | reverse_cost
----+--------+--------+------+--------------
1 | 1 | 1 | -1 | -1
(1 row)
```

For two isolated vertices:

```
id | source | target | cost | reverse_cost
----+--------+--------+------+--------------
1 | 1 | 2 | -1 | -1
2 | 2 | 1 | -1 | -1
(2 rows)
```

But in both the cases, the source and target vertices were not created, and the edge was not added.

(If I checked it correctly)

In my opinion, both the source and target vertices should get created, with no edge between them.

(If I checked it correctly)

In my opinion, both the source and target vertices should get created, with no edge between them.

While creating a graph in pgRouting, we call the

`insert_edges`

function which then calls the `graph_add_edge`

function. But the second function returns directly if both the cost and reverse_cost are negative (i.e. when the edge does not exist in the graph).