Reputation: 85
Within each for loop iteration I keep generating 2 sets of numpy arrays. Let's call the first numpy array 'A' and the second numpy array 'B'.
So A could look something like, where the length of A can vary:
[[ 0.94 -0.04]
[ 0.94 -0.03]
[ 0.98 -0.01]
[ 0.98 0. ]
[ 0.98 0.01]
[ 0.99 0.01]
[ 0.99 0.02]
[ 0.99 0.03]
[ 0.99 0.04]
[ 0.99 0.94]
[ 0.99 0.95]]
Let each 'vector' in A be a node of an undirected and weighted graph, so for eg [ 0.94 -0.04] is a node, [ 0.94 -0.03] is another node and so on.
And B would look something like and will only take the format of [X,Y]:
[ 0.99 -0.01]
Where [ 0.99 -0.01] is another node
Now I need to create an undirected and weighted graph such that [ 0.99 -0.01] is connected to each of the nodes in numpy array A, with a weight of given mathematical formula between the two node vectors.
For eg.
[ 0.99 -0.01] connected to [ 0.94 -0.04] with scalar weight np.linalg.norm([ 0.99 -0.01] - [ 0.94 -0.04])
[ 0.99 -0.01] connected to [ 0.94 -0.03] with scalar weight np.linalg.norm([ 0.99 -0.01] - [ 0.94 -0.03])
And so on...
Now, the last condition is that after each for loop iteration you may get combinations of vectors such that the connection already exists in the graph (i.e repeat of combination of vectors), which in that case we need to ignore and only look for vector combinations such that the graph does not already have and append the graph to make a connection of those two vectors with a given weight.
Can someone please help with formulating an ideal solution? Thanks.
Upvotes: 0
Views: 1321
Reputation: 2551
The error you're getting is because numpy.array
is a mutable type, and hence not hashable (see "hashable" entry in the Python glossary). If I'm not mistaken networkx
uses dictionaries to represent graphs under the hood, so I'll use Python dict
to showcase an example solution. If you try to use a numpy.array
as a key in a dict
you're get the same "unhashable type" error:
import numpy as np
b = np.array((1,2))
a = {b:"value"}
A possible solution is to convert it to an immutable type, for example, a tuple. The following would work:
import numpy as np
b = np.array((1,2))
a = {tuple(b):"value"}
With that in mind, let's create an undirected graph with networkx
:
import networkx as nx
import numpy as np
#generate some random data
a = np.random.randint(low=1, high=10,size=(4,2))
b = np.random.randint(low=1, high=10,size =(2,))
#create a undirected graph
g = nx.graph.Graph()
# define a function that takes two arrays and returns a scalar -- weight
def w(a,b):
return np.linalg.norm(b - a)
# cast np.arrays as tuples and use w to compute weights to get a list of edges
edges = [(tuple(x), tuple(b), w(x,b)) for x in a]
# add weighted edges to the graph
g.add_weighted_edges_from(edges)
# check if it worked (for a small sample)
for x in g.adjacency():
print(x)
Note that because the graph is undirected a pair of nodes (an edge) will appear twice, so an undirected edge from a to b, will appear as two edges (a,b) and (b,a).
Upvotes: 1