The following is a graph that I'm using to find neighbours of green nodes.
Green nodes are in a different set called new = [12,13,14,15,16,17,18,19,20,21,22,23,24,25].
When I access the first green node 12; it has it has two neighbours 15 and 21.But 21 has another green neighbours and hence I need them to be in my list of neighbours of node 12.This should be repeated until green nodes meet the red ones. So ultimately, the set of neighbours of node 12 should be [0,15,21,14,16,134,23,19,3]. can someone please help me to find this?
Pseudo-code since you didn’t at all specify how your graph works:
def findNeighbors (node, greens, visited = None):
if visited is None:
visited = set()
for n in node.directNeighbors:
# visit node if it’s new
if n not in visited:
visited.add(n)
# go recursively if the new node is green
if n in greens:
findNeighbors(n, greens, visited)
return visited
greenNodes = set(new)
twelve = findNodeByValue(12)
result = findNeighbors(twelve, greenNodes)
Related
I have a file shows different points' coordinates(first 10 rows):
1 10.381090522139 55.39134945301
2 10.37928179195319 55.38858713256631
3 10.387152479898077 55.3923338690609
4 10.380048819655258 55.393938880906745
5 10.380679138517507 55.39459444742785
6 10.382474625286 55.392132993022
7 10.383736185130601 55.39454404088371
8 10.387334283235987 55.39433237195271
9 10.388468103023115 55.39536574771765
10 10.390814951258335 55.396308397998475
Now I want to calculate the MST(minimum spanning tree) of them so firstly I change my coordinates to weight graph(distance->weight):
n = 10
data = []
for i in range(0, n):
for j in range(i + 1, n):
temp = []
temp.append(i)
temp.append(j)
x = np.array(rawdata[i, 1:3])
y = np.array(rawdata[j, 1:3])
temp.append(np.linalg.norm(x - y))
data.append(temp)
Then, using networkx to load weight data:
G = nx.read_weighted_edgelist("data.txt")
T = nx.minimum_spanning_tree(G)
nx.draw(T)
plt.show()
but I cannot see the orignal shape from result:
how to solve this problem?
I'm just answering the question about the position of the nodes. I can't tell from what you've done whether the minimum spanning tree is what you're after or not.
When you plot a network, it will assign positions based on an algorithm that is in part stochastic. If you want the nodes to go at particular positions, you will have to include that information in the call in an optional argument. So define a dictionary (it's usually called pos) such that pos[node] is a tuple (x,y) where x is the x-coordinate of node and y is the y-coordinate of node.
Then the call is nx.draw(T, pos=pos).
I have a simpel Card Game, which I am currently working on for my thesis.
The Rules are simpel. You have a deck of 52 Cards, from 1 to 10 and jack, queen, knight.
You draw a card from your Deck. If its a Number it gets added to your Account. If you draw a jack, queen or knight, your account gets reset to 0. After every draw you can decide if you want to draw again or stop.
For this game, i programmed a code with the help of this site.
It should give the probability, that you draw exactly "target".
So for example, the probability to draw, so that you have 1 Point in your account,
is 4/52, since you have four 1´s. The Programm does give me exactly this value.
But. The probabiltity, that you have exactly 2 points in your account is
4/52 + 4/52*3/51. You can either draw a 2 with prob of 4/52 or a 1 and another 1 with prob 4/52*3/51.
Here the code messes up. It calculates the probability to have exactly 2 points in your account as
4/52 + 4/52*4/51 and i dont get why?
Can anyone help me?
import collections
import numpy as np
def probability(n, s, target):
prev = {0: 1} # previous roll is 0 for first time
for q in range(n):
cur = collections.defaultdict(int) # current probability
for r, times in prev.items():
cards = [card for card in range(1, 11)] * 4
for i in cards[:]:
cards.remove(i)
# if r occurred `times` times in the last iteration then
# r+i have `times` more possibilities for the current iteration.
cur[r + i] += times
prev = cur # use this for the next iteration
return (cur[t]*np.math.factorial(s-n)) / (np.math.factorial(s))
if __name__ == '__main__':
s = 52
for target in range(1, 151):
prob = 0
for n in range(1, 52):
prob += probability(n, s, target)
print(prob)
EDIT: I am fairly sure, that the line
for i in [i for i in cards]:
is the problem. Since cards.remove(i) removes the drawn card, but i doesnt care and can draw it anyway.
EDIT 2: Still searching. I tried the suggestions in this two qestions
How to remove list elements in a for loop in Python?
and
How to remove items from a list while iterating?
Nothing worked so far as it should.
I'm assuming with probability(n, s, target) you want to calculate the probability if you draw exactly n out of s cards that the sum of values is exactly target.
Then you will have a problem with n>=2. If I understand this right, for every iteration in the loop
for q in range(n):
you save in cur[sum] the number of ways to reach sum after drawing one card (p=0), two cards (p=1) and so on. But when you set p=1 you don't "remember" which card you have already drawn as you set
cards = [i for i in range(1, 11)] * 4
afterwards. So if you have drawn a "1" first (four possibilities) you have again still four "1"s you can draw out of your deck, which will give you your 4/52*4/51.
As a side note:
Shouldn't there be some kind of check if i==11 since that should reset your account?
I have solved it. After like a 4 Days.
This is the Code:
import numpy as np
def probability(cards, target, with_replacement = False):
x = 0 if with_replacement else 1
def _a(idx, l, r, t):
if t == sum(l):
r.append(l)
elif t < sum(l):
return
for u in range(idx, len(cards)):
_a(u + x, l + [cards[u]], r, t)
return r
return _a(0, [], [], target)
if __name__ == '__main__':
s = 52 # amount of cards in your deck
cards = [c for c in range(1, 11)] * 4
prob = 0
for target in range(1, 151): # run till 150 points
prob = probability(cards, target, with_replacement = False)
percentage = 0
for i in range(len(prob)):
percentage += np.math.factorial(len(prob[i])) * np.math.factorial(s-len(prob[i]))/(np.math.factorial(s))
print(percentage)
This Code is the Solution to my Question. Therefore this Thread can be closed.
For those who want to know, what it does as a tl;dr version.
You have a List (in this case Cards). The Code gives you every possible Combination of Elements in the List such as the Sum over the elements equals the target Value. Furthermore it also gives the Probability in the above mentioned Cardgame to draw a specific Value. The above mentioned game is basically the pig dice game but with cards.
I am attempting to autoscale a networkx graph based on the number of nodes and whether there are nodes that overlap in the horizontal direction or the vertical direction (ie. if all nodes were on the same line, they would intersect). To do this, I look at the position of each node and check whether the position plus the node size is between any other nodes coordinates plus the node size. To get the node positions, I am using networkx.nx_agraph.graphviz_layout. The issue is that the positions and the node size are not of the same unit.
Networkx calls pyplot.scatter underneath the hood (source: https://networkx.github.io/documentation/networkx-1.10/_modules/networkx/drawing/nx_pylab.html#draw_networkx_nodes), which takes the node size as an area in pixels (source: https://stackoverflow.com/questions/14827650/pyplot-scatter-plot-marker-size).
Networkx draws the graph with circle nodes, so based on this it would make sense that to convert the node size to inches, I would do node_size * 4 / (math.pi * DPI) where DPI is the DPI used by Matplotlib. In my code this does not seem to work. I have also tried taking the square root of the node size and dividing it by the DPI but that doesn't seem to work either.
Currently the issue is that I am not able to detect what nodes are overlapping.
In summary: If I am plotting a networkx graph with circle nodes, how can I convert the node size and/or the Pygraphviz positions to a common unit?
It could also be that my code is wrong, so here is a short reproducible example:
NODE_SIZE = 300
DPI = 100
mpl.rcParams['figure.dpi'] = DPI
G = nx.gnp_random_graph(50, 0)
pos = nx.nx_agraph.graphviz_layout(G)
tmp_pos = sorted(pos.items(), key=lambda x: x[1][0]) # Sort it by x value so you only have to check to the right of the node in the list of positions
node_size_inches = NODE_SIZE * 4 / (math.pi * DPI) # This is my attempt at getting the height/width of the nodes
i = 0
for key, xy in tmp_pos:
x = xy[0]
overlapping = []
# Since list is sorted by x, you only need to check nodes to the right
for k, xyt in tmp_pos[i+1:]:
xt = xyt[0]
# Check for overlapping nodes to the right
if x <= xt <= x + node_size_inches:
overlapping.append(k)
# Since list is sorted by x, if the previous condition fails, nothing after can be applicable
else:
break
if overlapping: print("{}:{}".format(key, overlapping))
i += 1
nx.draw(G, pos=pos, with_labels=True)
I've been trying to do this for a long time without success, so I'd better ask you.
First of all, I'm working on python 3 and networkx.
I have a bipartite graph as the image A, in which there are two types of nodes according to their 'group' attribute (group='R' and group='X'). Also, some relationships are reversible, as R4, and some are not (so I guess we would have to unfold the node in those cases).
What I need is to leave only the nodes of the R group and eliminate the X ones, but keeping the relations between them. That is, convert the green nodes into edges and keep a graph of only blue nodes.
Ohhh please!!, Can someone give me a hand?
Any help would be very welcome.
Thank you in advance wholeheartedly!
GRAPH IMAGE HERE:
https://media.springernature.com/full/springer-static/image/art%3A10.1038%2Fs41540-018-0067-y/MediaObjects/41540_2018_67_Fig1_HTML.png
Go over nodes of the graph, if the node is green add an edge between all its neighbours (which will only be blue). At the end remove all the green nodes.
to_remove = []
for node in G.nodes(data = True):
if node[1]["type"] == "Green": ## check if the node is green
to_remove.append(node[0])
## go over all neighbours of the node and add an edge between them
neighbours = list(G.neighbors(node[0]))
for i in range(0, len(neighbours)-1):
for j in range(i+1, len(neighbours)):
G.add_edge(neighbours[i],neighbours[j])
## remove the green nodes
G.remove_nodes_from(to_remove)
I came across a rope tree as an alternative data structure for a string.
http://en.wikipedia.org/wiki/Rope_(data_structure)
To concat is easy, but I am stuck on the split operation. The wikipedia article states:
For example, to split the 22-character rope pictured in Figure 2.3 into two equal component ropes of length 11, query the 12th character to locate the node K at the bottom level. Remove the link between K and the right child of G. Go to the parent G and subtract the weight of K from the weight of G. Travel up the tree and remove any right links, subtracting the weight of K from these nodes (only node D, in this case). Finally, build up the newly-orphaned nodes K and H by concatenating them together and creating a new parent P with weight equal to the length of the left node K.
Locating the character and recombining the orphans is no problem. But I don't understand the "Travel up the tree and remove any right links, subtracting the weight of K from these nodes". The example stops at D, but if you follow these instructions verbatim you would continue onto B and remove D as well. What is the correct stopping requirement in this algorithm? And how do you avoid nodes with only one (left or right) child?
A pseudo-code algorithm explaining this part would help tremendously.
The wikipedia article is not very explicit. If the current node is X and its parent is Y you would only travel up if X is the left child of Y. Visually you're going up and to the right as far as you can.
I give Ruby code below. It's as close to executable pseudocode as you'll get. If Ruby isn't right for your implementation, you can always use it as a prototype. If you don't like the recursion, it's easy enough to use standard transformations to make it iterative with an explicit stack.
The natural implementation of split is recursive. The interesting case is near the bottom of the code.
class Rope
# Cat two ropes by building a new binary node.
# The parent count is the left child's length.
def cat(s)
if self.len == 0
s
elsif s.len == 0
self
else
Node.new(self, s, len)
end
end
# Insert a new string into a rope by splitting it
# and concatenating twice with a new leaf in the middle.
def insert(s, p)
a, b = split_at(p)
a.cat(Leaf.new(s)).cat(b)
end
end
class Leaf < Rope
# A leaf holds characters as a string.
attr_accessor :chars
# Construct a new leaf with given characters.
def initialize(chars)
#chars = chars
end
# The count in this rope is just the number of characters.
def count
chars.length
end
# The length is kind of obvious.
def len
chars.length
end
# Convert to a string by just returning the characters.
def to_s
chars
end
# Split by dividing the string.
def split_at(p)
[ Leaf.new(chars[0...p]), Leaf.new(chars[p..-1]) ]
end
end
class Node < Rope
# Fields of the binary node.
attr_accessor :left, :right, :count
# Construct a new binary node.
def initialize(left, right, count)
#left = left
#right = right
#count = count
end
# Length is our count plus right subtree length. Memoize for efficiency.
def len
#len ||= count + right.len
end
# The string rep is just concatenating the children's string reps.
def to_s
left.to_s + right.to_s
end
# Split recursively by splitting the left or right
# subtree and recombining the results.
def split_at(p)
if p < count
a, b = left.split_at(p)
[ a, b.cat(right) ]
elsif p > count
a, b = right.split_at(p - count)
[ left.cat(a), b ]
else
[ left, right ]
end
end
end
After some tinkering and consideration, I think the rules should be this:
First determine the starting point for traveling upwards.
A) If you end up in the middle of a node (node A), split the string at the right character index and create a left and right node. The parents of these new nodes is node A. The left node is your starting point. The right node will be added to the orphans while traveling up.
B) if you end up at the beginning of a node (character wise) and this node is a right node: split of this node (=> orphan node) and use the parent node as your starting point.
C) if you end up at the beginning of a node (character wise) and this node is a left node:
split of this node (=> orphan node) and use this node as your starting point.
D) if you end up at the end of a node (character wise) and this node is a right node:
use the parent node as your starting point
D) if you end up at the end of a node (character wise) and this node is a left node:
use this node as your starting point.
During traveling:
If the node is a left node: move upwards and add its right sibling node to the list of orphans.
If the node is a right node: move upwards (to parent A), but do nothing with the left sibling node. (Or, because all the right nodes up to this point have been orphaned, you could set the starting point as the right node of the parent node A. The parent node A is then your new starting point. This avoids a bunch of nodes with only 1 child node.)
After
Concat all the accumulated orphans into a new Node. This is the right part of your new rootNode. The left part is the endpoint of your travel sequence.
Please correct me if I am wrong.