I have a networkX graph where every node has an attribute.
I need to extract nodes based on a numerical attribute made in the range [0,inf] to create edges.
I tried using random.choice(G.nodes(), p) with p=attribute/(sum of the attributes in the graph).
The problem is that everytime i extract a node to create the edge my attribute change (for example let's say the attribute+=1) so I need to update all the probabilities because also the sum increases by 1.
For example I could have a graph with G.nodes(data=True)={1:{att=10},2:{att=5}, 3:{att=2}}
So p=[10/17, 5/17, 2/17].
If I extract for example 1 at the first extraction my graph will be G.nodes(data=True)={1:{att=11},2:{att=5}, 3:{att=2}} and p=[11/18, 5/18, 2/18].
Now, because i have more than a thousand graph and for every one of them I need to do a 50000 for clause that create edges, it's not computationally feasible to update all the probability every time i create an edge.
Is there a way to just use the node's attribute or to not calculate my probability every time?
By using numpy array I have done this:
G=nx.Graph()
G.add_nodes_from([1,2,3])
G.nodes[1]["att"]=10
G.nodes[2]["att"]=5
G.nodes[3]["att"]=2
dict={}
for i in G.nodes():
dict[i]=G.nodes[i]["att"]
extracted=random.chance(G.nodes(),p=np.fromiter(dict.values(),dtype="float")/np.sum(np.fromiter(dict.values(),dtype="float")))
When extracted (for example node 1) G.nodes[1]["att"]+=1 and nothing else need to be updated
Related
Context
This is the first time I have to work with NetworkX so either I can't read correctly the documentation, or I simply do not use the right vocabulary.
Problem
I am working with a DiGraph, and I want to get a list of every nodes accessible starting from a specified node.
I thought of making a sub-graph containing the nodes I just described, and I would siply have to iterate over that specific sub-graph. Unfortunately, I didn't find a way to create automatically a sub-graph with the condition I mentioned.
It feels like an obvious feature. What am I missing ?
You are looking for the nx.descendants method:
descendants(G, source)
Return all nodes reachable from
(source) in G.
Parameters : G : NetworkX DiGraph
source : node in G
Returns : des : set()
The descendants of source in G
I am trying to use the python NetworkX package to validate some other code, but I am worried that load centrality does not mean what I think. When I run the example below, I expect to only get integer values for load since it should just be a count at each node of the number of shortest paths passing through the node (i.e., I list out all the shortest paths between node pairs, then for each node 'v' count how many paths cross it, excluding paths where 'v' is the first or last node):
edges = [ ('a0','a1'),('a0','a2'),('a1','a4'),('a1','a2'),('a2','a4'),('a2','z5'),('a2','a3'),('a3','z5'),('a4','z5'),('a4','z6'),('a4','z7')
,('z5','z6'),('z5','z7'),('z5','z8'),('z6','z7'),('z6','z8'),('z6','z9'),('z7','z8'),('z7','z9'),('z8','z9')]
import networkx as nx
testg = nx.Graph( edges )
nx.load_centrality( testg, normalized=False )
I get output like this:
{'a0': 0.0,
'a1': 3.16666665,
'a2': 15.4999998,
'a3': 0.0,
'a4': 14.75,
'z5': 20.25,
'z6': 6.04166666,
'z7': 6.04166666,
'z8': 2.24999996,
'z9': 0,0}
These are similar to the values I compute by hand in terms of relative size, but why aren't they integer values? Every other network that I have tested returns integer values for unnormalized load centrality, and I don't see anything in the definition that would lead to these values. The python doc for this function says to see betweenness and also provides an article as reference for the algorithm (which I can't access).
After very extensive calculations based on the paper Downshift linked to, it looks like 'load' follows the betweenness definition in that paper but subtracts off a factor of (2n-1) to adjust for some overcounting in the algorithm. Either that, or the algorithm in the paper doesn't make clear that the initial packets of size '1' should only contribute to nodes they pass through and not to the ends of the paths. In any case, I can match the output values of networkx now. The values differ from networkx's own betweenness function which follows the formula in the documentation based on node pairs rather than propagating packets of size 1 through the network.
In particular, because the packets split into equal size at branch points, nodes can accumulate partial packets and therefore accumulate a non-integer 'load' value. That's not what the description implies in the networkx documentation, but it's clear enough now.
I wanted to extract stress on top surface of my model on each node but it can't be done normally. when I use this script:
odb = visualization.openOdb('My.odb')
frame=odb.steps['AStep'].frames[-1]
dispNode = odb.rootAssembly.nodeSets['UPPER']
STRESS= frame.fieldOutputs['S'].getSubset(region=dispNode).values
COORD= frame.fieldOutputs['COORD'].getSubset(region=dispNode).values
print(STRESS)
print(COORD[1].data)
STRESS returns an empty array.
How can I edit my script to have stress and its corresponding coordinates??
Your Code can't work, if you only calculated your stress values on the integration points. There are simply no values at the nodes, so if you request values at nodes you will get an empty array.
This is how it should work:
Extrapolate your integration point results to the nodes
Average your ElementNodal values. This is how that works: https://stackoverflow.com/a/43175485/4045774
Extract your node coordinates (deformed or undeformed)
get the node labels from your point set
With the node labels from your point set find the corresponding unique nodal values https://docs.scipy.org/doc/numpy/reference/generated/numpy.in1d.html
If you need a small example code, feel free to ask.
I'm working on a small project involving cluster, and I think the code given here https://www.ics.uci.edu/~eppstein/PADS/UnionFind.py might be a good starting point for my work. However, I have come across a few difficulties implementing it to my work:
If I make a set containing all my clusters cluster=set([0,1,2,3,4,...,99]) (there are 100 points with the numbers labelling them), then I would like to to group the numbers into cluster, do I simply write cluster=UnionFind()? Now what is the data type of cluster?
How can I perform the usual operations for set on cluster? For instance, I would like to read all the points (which may have been grouped together) in cluster, but type print cluster results in <main.UnionFind instance at 0x00000000082F6408>. I would also like to keep adding new elements to cluster, how do I do it? Do I need to write the specific methods for UnionFind()?
How do I know all the members of a group with one of its member is called? For instance, 0,1,3,4 are grouped together, then if I call 3, I want it to print 0,1,3,4, how do I do this?
thanks
Here's a small sample code on how to use the provided UnionFind class.
Initialization
The only way to create a set using the provided class is to FIND it, because it creates a set for a point only when it doesn't find it. You might want to create an initialization method instead.
union_find = UnionFind()
clusters = set([0,1,2,3,4])
for i in clusters:
union_find[i]
Union
# Merge clusters 0 and 1
union_find.union(0, 1)
# Add point 2 to the same set
union_find.union(0, 2)
Find
# Get the set for clusters 0 and 1
print union_find[0]
print union_find[1]
Getting all Clusters
# print all clusters and their sets
for cluster in union_find:
print cluster, union_find[cluster]
Note:
There is no direct way that gets you all the points given a cluster number. You can loop over all the points and pick the ones that have the required cluster number. You might want to modify the given class to support that operation more efficiently.
In networkx
gr.nodes(data=True)
returns the list of nodes along with the attributes present on each node. Is it possible to get all the neighbors along with attributes of a given node in the graph.
Neighbors function doesn't accept any optional boolean parameter.
Use the adjacency_iter if you want to iterate over them or adjacency_list if you want them as a list.
Edit
I should add that neither of those will give you the attributes of node. But you can get them easily with g.node[n].