I have created a multidigraph of motorway of Netherlands using osmnx package.
The graph is a multidigraph returned from osmnx. Since I am interested to compute k-shortest paths between an origin and a destination, I tried networkx library. However, networkx does not seem to work with multidigraph. All I can compute the shortest path.
I would like to ask if there is any other way to perform the k-shortest path computation in python over multidigraph.
Try using the networkx command shortest_simple_paths (documentation).
It returns a generator which returns one path at a time from shortest to longest.
G = nx.karate_club_graph()
X = nx.shortest_simple_paths(G, 0, 5)
k = 5
for counter, path in enumerate(X):
print(path)
if counter == k-1:
break
> [0, 5]
> [0, 6, 5]
> [0, 10, 5]
> [0, 6, 16, 5]
> [0, 4, 6, 5]
This will work with DiGraphs, but I'm not sure about a MultiDiGraph. It's not clear to me that a road network would be a MultiDiGraph, however.
Related
Trying to find the Jordan form of a given matrix using Colab.
But it always fails or times out.
Not sure why is this failing
import numpy as np
import sys
from sympy import Matrix
sys.set_int_max_str_digits(15000)
a = np.array([[1, 2, 4, 8], [1, 3, 9, 27], [1, 4, 16, 64], [1, 5, 25, 125]])
m = Matrix(a)
P, J = m.jordan_form()
J
I tried finding Jordan form on Matlab and on online calculators like
https://www.wolframalpha.com/input/?i=jordan+normal+form+calculator
It works fine on these platforms.
Not sure why Colab and Jupyter are not able to compute the Jordan form of the matrix
Firstly, Colab and Jupyter are simply environments in which you can run Python codes, and the issue here has nothing to do with using Colab or Jupyter or any IDE.
Secondly, the reason you do not get the results in your example is an algorithmic one. The matrix you are using is ill-conditioned. There is four orders of magnitude difference between the four egnevalues. And the underlying algorithm gets stuck while trying to calculate the Jordan form.
If you try, as an example:
a = np.array([[5, 4, 2, 1], [0, 1, -1, -1], [-1, -1, 3, 0], [1, 1, -1, 2]])
you will see you code works well and fast.
I'm using python 3.9.1 and trying to understand the bisect in 2d array.
I have a list of list like below and trying to insert a value to it using bisect.insort,
but nothing works.
How to make it work?
l = [[[-1, 0], [0, 5], [3, 5]],
[[-1, 0], [2, 6]],
[[-1, 0], [1, 10]]]
l.sort(key=lambda x: x[1])
bisect.insort(l, 4) # 1
bisect.insort(l, [4]) # 2
bisect.insort(l, [4,1]) # 3
print(f"l ={l}")
all three #1 - #3 are throwing TypeError.
How to insert a list to the list of lists by using insort in ?
You stopped one version too soon:
bisect.insort(l, [[4,1]])
Which may not produce what you want, but you never made clear exactly what that was. (And l is a list of lists of lists.)
Problem scale- I am taking OSM Road network of a city (6000 nodes and 50000 edges.)
Input - The graph is read as a netwrokx Digraph. (weighted)
For a given node r, I want to construct shortest path tree. Is there a standard Networkx function or library which can do so ? If not, How can I do this efficiently ? ( as opposed to running Dijkstra for all r-v pair)
Input in any form is highly valued!
This function returns the shortest path, from any node to every node reachable
Here's an example of its output:
For the following (very simple) graph:
G = nx.path_graph(5)
the single_source_shortest_path function:
path_1 = nx.single_source_shortest_path(G, 1)
returns:
{1: [1], 0: [1, 0], 2: [1, 2], 3: [1, 2, 3], 4: [1, 2, 3, 4]}
Where the shortest path from node 1 to any target T is returned by path_1[T].
There is also a networkX built-in solution to run Dijkstra for every node pair(docs):
shortest_paths = dict(nx.all_pairs_dijkstra_path(G))
shortest_paths[1]
# returns {1: [1], 0: [1, 0], 2: [1, 2], 3: [1, 2, 3], 4: [1, 2, 3, 4]}
I have a Delaunay Triangulation (DT) (scipy) as follows:
# Take first 50 rows with 3 attributes to create a DT-
d = data.loc[:50, ['aid', 'x', 'y']].values
dt = Delaunay(points = d)
# List of triangles in the DT-
dt.simplices
'''
array([[1, 3, 4, 0],
[1, 2, 3, 0],
[1, 2, 3, 4]], dtype=int32)
'''
Now, I want to create a graph using 'networkx' package and add the nodes and edges found using DT from above.
# Create an empty graph with no nodes and no edges.
G = nx.Graph()
The code I have come up with to add the unique nodes from DT simplices into 'G' is-
# Python3 list to contain nodes
nodes = []
for simplex in data_time_delaunay[1].simplices.tolist():
for nde in simplex:
if nde in nodes:
continue
else:
nodes.append(nde)
nodes
# [1, 3, 4, 0, 2]
# Add nodes to graph-
G.add_nodes_from(nodes)
How do I add edges to 'G' using 'dt.simplices'? For example, the first triangle is [1, 3, 4, 0] and is between the nodes/vertices 1, 3, 4 and 0. How do I figure out which nodes are attached to each other and then add them as edges to 'G'?
Also, is there a better way to add nodes to 'G'?
I am using Python 3.8.
Thanks!
You could add the rows in the array as paths. A path just constitutes a sequence of edges, so the path 1,2,3 translates to the edge list (1,2),(2,3).
So iterate over the rows and use nx.add_path:
simplices = np.array([[1, 3, 4, 0],
[1, 2, 3, 0],
[1, 2, 3, 4]])
G = nx.Graph()
for path in simplices:
nx.add_path(G, path)
nx.draw(G, with_labels=True, node_size=500, node_color='lightgreen')
Say we have two matrices A and B with a size of 2 by 2. Is there a command that can stack them horizontally and add A[:,1] to B[:,0] so that the resulting matrix C is 2 by 3, with C[:,0] = A[:,0], C[:,1] = A[:,1] + B[:,0], C[:,2] = B[:,1]. One step further, stacking them on diagonal so that C[0:2,0:2] = A, C[1:2,1:2] = B, C[1,1] = A[1,1] + B[0,0]. C is 3 by 3 in this case. Hard coding this routine is not hard, but I'm just curious since MATLAB has a similar function if my memory serves me well.
A straight forward approach is to copy or add the two arrays to a target:
In [882]: A=np.arange(4).reshape(2,2)
In [883]: C=np.zeros((2,3),int)
In [884]: C[:,:-1]=A
In [885]: C[:,1:]+=A # or B
In [886]: C
Out[886]:
array([[0, 1, 1],
[2, 5, 3]])
Another approach is to to pad A at the end, pad B at the start, and sum; while there is a convenient pad function, it won't be any faster.
And for the diagonal
In [887]: C=np.zeros((3,3),int)
In [888]: C[:-1,:-1]=A
In [889]: C[1:,1:]+=A
In [890]: C
Out[890]:
array([[0, 1, 0],
[2, 3, 1],
[0, 2, 3]])
Again the 2 arrays could be pad and added.
I'm not aware of any specialized function to do this; even if there were, it probably would do the same thing. This isn't a common enough operation to justify a compiled version.
I have built up finite element sparse matrices by adding over lapping element matrices. The sparse formats for both MATLAB and scipy facilitate this (duplicate coordinates are summed).
============
In [896]: np.pad(A,[[0,0],[0,1]],mode='constant')+np.pad(A,[[0,0],[1,0]],mode='
...: constant')
Out[896]:
array([[0, 1, 1],
[2, 5, 3]])
In [897]: np.pad(A,[[0,1],[0,1]],mode='constant')+np.pad(A,[[1,0],[1,0]],mode='
...: constant')
Out[897]:
array([[0, 1, 0],
[2, 3, 1],
[0, 2, 3]])
What's the special MATLAB code for doing this?
in Octave I found:
prepad(A,3,0,axis=2)+postpad(A,3,0,axis=2)