OpenstreetmapX.jl routing using subnetworks - julia

I am using OpenstreetmapX.jl library to calculate routes between to points of my OSM network.
Is there any way to obtain such routes limiting the results to paths of a predefined sub network?
For instance, I would like to calculate the route between two points but only using secondary roadways.
Is it possible?

Most likely you would like to create a separate MapData object for processing such data. There is a nice tool osmfilter that allows to filter out specific route types before importing data to Julia.
In this way you can have separate representations of your map data.
However, if you want to operate directly on the MapData object you could set the distance weights to Inf and which would force the routing algorithm to avoid such edges or return Inf route length.
Suppose you have the map from the tutorials:
using OpenStreetMapX, Graphs
map_file_path = joinpath(dirname(pathof(OpenStreetMapX)),"..","test/data/reno_east3.osm")
mx = get_map_data(map_file_path, use_cache=false);
Than you could do to filter out secondary routes:
m2 = deepcopy(mx)
edgs = collect(edges(mx.g))[findall(!=(4), mx.class)]
setindex!.(Ref(m2.w), Inf, src.(edgs), dst.(edgs))
Now the selected route will differ between mx and m2:
julia> shortest_route(mx, 3073938243, 3101115892)
([3073938243, 3073938154, 140340636, 140340638, 3101117891, 3101115892], 549.9261168024648, 32.32592992211371)
julia> shortest_route(m2, 3073938243, 3101115892)
([3073938243, 140533189, 140533195, 3101115892], 617.4395184717641, 54.94654519330738)

Related

what does "not strongly connected graph" means in centiserve centroid computation?

As in the question, I have four different networks which I load from 4 different csv files. Each one fails when I compute the centroid using centiserve library. On the other hand, if I generate a random ER network, the centroid computation works.
I looked into the centroid funcion and eventually I found it checks whether the network is connected using an igraph this function is.connected(g, mode="strong")
According to wikipedia a graph is strongly connected if all the nodes are reachable from a random node in the network. To this aim, I calculated the components of my network, using igraph's decompose() function and all the networks have a single connected component: length(decompose(net)) is always equal to 1. But, centroid(net) is always returning the error.
Eventually, the question is: What exactly is this function looking for when it verifies if the graph is suitable? Why my network has a single connected component but the is.connected() function of igraph return False?
Some code:
#load file
finalNet <- read.csv("net.csv", sep=",", header=T)
#get network
net <- graph_from_data_frame(finalNet[, c(1, 2)])
#decompose says that there is a single connected component
length(decompose(net))
#while centroid does not work!
centroid(net)
the network is available here
ok, I found the answer. The problem is that the function graph_from_data_frame create a directed network, if not specified otherwise.
Hence, the solution to make my example work is to load the network as not directed:
net <- graph_from_data_frame(finalNet[, c(1, 2)], directed=F)

Julia module for subgraphing a graph (nodes / vertices and edges) without changing or relabeling node indices?

Terminology note: "vertices"="nodes", "vertex/node labels" = "indices"
LightGraphs in Julia changes node indices when producing induced subgraphs.
For instance, if a graph has nodes [1, 2, 3, 4], its LightGraphs.induced_subgraph induced by nodes [3,4] will be a new graph with nodes [3,4] getting relabeled as [1,2].
In state-of-the-art graph algorithms, recursive subgraphing is used, with sets of nodes being modified and passed up and down the recursion layers. For these algorithms to properly keep track of node identities (labels), subgraphing must not change the indices.
Subgraphing in networkx in Python, for instance, preserves node labels.
One can use MetaGraphs by adding a node attribute :id, which is preserved by subgraphing, but then you have to write a lot of extra code to convert between node indices and node :id's.
Is there not a Julia package that "just works" when it comes to subgraphing and preserving node identities?
I'd first like to take the opportunity to clarify some terminology here: LightGraphs itself doesn't dictate a graph type. It's a collection of algorithms and an interface specification. The limitations you're seeing are for SimpleGraphs, which is a graph type that ships with the LightGraphs package and is the default type for Graph and DiGraph.
The reason this is significant is that it is (or at least should be) very easy to create a graph type that does exactly what you want and that can take advantage of the existing LightGraphs infrastructure. All you (theoretically) need to do is to implement the interface functions described in src/interface.jl. If you implement them correctly, all the LightGraphs algorithms should Just Work (tm) (though they might not be performant; that's up to the data structures you've chosen and interface decisions you've made).
So - my advice is to write the graph structure you want, and implement the dozen or so interface functions, and see what works and what doesn't. If there's an existing algorithm that breaks with your interface implementation, file a bug report and we'll see where the problem is.

Traverse Graph With Directed Cycles using Relationship Properties as Filters

I have a Neo4j graph with directed cycles. I have had no issue finding all descendants of A assuming I don't care about loops using this Cypher query:
match (n:TEST{name:"A"})-[r:MOVEMENT*]->(m:TEST)
return n,m,last(r).movement_time
The relationships between my nodes have a timestamp property on them, movement_time. I've simulated that in my test data below using numbers that I've imported as floats. I would like to traverse the graph using the timestamp as a constraint. Only follow relationships that have a greater movement_time than the movement_time of the relationship that brought us to this node.
Here is the CSV sample data:
from,to,movement_time
A,B,0
B,C,1
B,D,1
B,E,1
B,X,2
E,A,3
Z,B,5
C,X,6
X,A,7
D,A,7
Here is what the graph looks like:
I would like to calculate the descendants of every node in the graph and include the timestamp from the last relationship using Cypher; so I'd like my output data to look something like this:
Node:[{Descendant,Movement Time},...]
A:[{B,0},{C,1},{D,1},{E,1},{X,2}]
B:[{C,1},{D,1},{E,1},{X,2},{A,7}]
C:[{X,6},{A,7}]
D:[{A,7}]
E:[{A,3}]
X:[{A,7}]
Z:[{B,5}]
This non-Neo4J implementation looks similar to what I'm trying to do: Cycle enumeration of a directed graph with multi edges
This one is not 100% what you want, but very close:
MATCH (n:TEST)-[r:MOVEMENT*]->(m:TEST)
WITH n, m, r, [x IN range(0,length(r)-2) |
(r[x+1]).movement_time - (r[x]).movement_time] AS deltas
WHERE ALL (x IN deltas WHERE x>0)
RETURN n, collect(m), collect(last(r).movement_time)
ORDER BY n.name
We basically find all the paths between any of your nodes (beware cartesian products get very expensive on non-trivial datasets). In the WITH we're building a collection delta's that holds the difference between two subsequent movement_time properties.
The WHERE applies an ALL predicate to filter out those having any non-positive value - aka we guarantee increasing values of movement_time along the path.
The RETURN then just assembles the results - but not as a map, instead one collection for the reachable nodes and the last value of movement_time.
The current issue is that we have duplicates since e.g. there are multiple paths from B to A.
As a general notice: this problem is much more elegantly and more performant solvable by using Java traversal API (http://neo4j.com/docs/stable/tutorial-traversal.html). Here you would have a PathExpander that skips paths with decreasing movement_time early instead of collection all and filter out (as Cypher does).

How can I compute a route/path of a certain length between two places?

Given two places in a region, how can I compute a path that is of certain distance (the distance is given as a parameter) which connects the two places. The resulting path should ideally be composed of roads that are visited no more than once.
I have learnt that this problem can be viewed as a graph problem where the roads in the map represent the edges of the graph and the intersection/junctions represent the nodes of the graph. From this the problem can be simplified to finding a path of certain length for any two nodes in the graph.
One of my approaches to this problem can be broken into two steps:
Finding the shortest path between the two nodes (using A* or a similar algorithm).
Extending/Expanding the shortest path that is returned from A* so that it's long enough.
Now, I am not exactly sure if this approach is worth pursuing or if a better approach exists? Also, I've not come across any methods that would allow me to expand the path - are there any specific techniques that can achieve this?
My idea is to use an ad-hoc heuristic function. The goal state should be reaching the destination with a path long L. (So if you reach the destination with a too short path the goal test is not satisfied and the algorithm will continue).
#goal state
if (state == dest and curr_length == required_length)
return path
For every other node the heuristic must give a value that is a combination of the expected distance from the destination and the required length that must still be travelled.
h(state, curr_length):
dist = manhattan_distance(state, goal)
#must use the abs instead if curr_length > required_length this value becomes
#negative and this node gets a wrong result
len = abs(required_length - curr_length)
return dist + len
I'm not sure if this heuristic is consistent or not, but you can try with something like this and check the results.
If this search work it should also be optimal.

BGL: How do I get direct access to data of nodes and edges?

I have another problem regarding the Boost Graphic Library which I could not answer myself by googling nor reading the documentation. It's not directly related to my other questions so I thought I'd better start a new thread.
I have a graph with an adjacency layout and use bundled properties to get access to the data of nodes and edges. I use a typedef for my Graph for convenience. Thus I can access the data which is stored, e.g. for a vertex_descriptor, by typing something like this:
Graph[my_vertex_descriptor].setX(4);
Graph[my_vertex_descriptor].setY(10);
Now I would like to define a reference to the data-storing object to be able to type something like that:
typedef Graph[vertex_descriptor]::type Vertex;
Vertex v = Graph[my_vertex_descriptor];
v.setX(4);
v.setY(10);
By this or a similar approach I seek to avoid unnecessary recalculations of the mapped value which is accessed by using the []operator of the map and a specific descriptor object. My vertices and edges contain lots of data so in certain situations my current code produces many recalculations of the same value to deal with this data. This seems to be ugly.
Does anybody know if it is possibly to achieve what I'm trying to do?
I used bundled properties and:
Bundled_vertex_property prop_v = get(vertex_bundle, my_graph) // or get(vertex_bundle, v, my_graph)
Bundled_edge_property prop_e = get(edge_bundle, my_graph) // or get(edge_bundle, v, my_graph)
to get the bundled property directly.
Off the top of my head, this should work (assuming you are using one of the built in graph types with a well defined graph_traits):
typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
Vertex v = Graph[my_vertex_descriptor];
v.setX(4);
v.setY(10);
you can actually access a lot this way, take a look at BGL's graph concepts for more info: http://www.boost.org/doc/libs/1_45_0/libs/graph/doc/graph_concepts.html

Resources