Graph Nodes Coordinates Evaluation

Get nodes positions in a randomly generated graph

Check nx.spring_layout docs here, look for the scale and k parameters:

scale (number (default: 1)) – Scale factor for positions. Not used unless fixed is None.


k (float (default=None)) – Optimal distance between nodes. If None the distance is set to 1/sqrt(n) where n is the number of nodes. Increase this value to move nodes farther apart.

As to getting integer coordinates, you can easily do this with int.

positions = { node: (int(pos[0]),int(pos[1])) for node,pos in node_positions.items() }

[Edit]

k is the parameter for Fruchterman-Reingold layout algorithm, it is kind of strength of repulsion between nodes.

I'd better show what it does (the same graph layed out with different k's):

k=0.001

k=0.001

k=0.1

k=0.1

What is the best way compare two nodes coordinates?

If I understand your question correctly, you want to check the closeness between two points (positions) which may or may not be far apart from each other.

Check out this function first:

int get_distance(std::pair<int, int> const pos_a, std::pair<int, int> const pos_b)
{
auto const distance_x = pos_a.first >= pos_b.first ? pos_a.first - pos_b.first : pos_b.first - pos_a.first;
auto const distance_y = pos_a.second >= pos_b.second ? pos_a.second - pos_b.second : pos_b.second - pos_a.second;
if (distance_x != 0 && distance_y != 0)
return int(round(sqrt(distance_x * distance_x + distance_y * distance_y)));
if (distance_x == 0)
return distance_y;
return distance_x;
}

Here, it calculates the distance between two points by subtracting it with the greatest number (Hence the two beginning statements) and the operator used is a Ternary Operator. (Click on the link if you don't know what that is)

The third line is an if statement evaluating whether both the acquired distances are non-zero because if they are, then they are on the same line vertically or horizontally...

If both are non-zero numbers, then square root sum of squares of both distance x and y is rounded off to the nearest integer and then cast itself to an integer (Since the return type is int)

On the other hand, if any one of them is a zero number (Hence, on the same line), then the distance X or Y will be returned respectively based on the axis of the line (Vertical or Horizontal, hence distance_x == 0 and distance_y == 0)

Now, for your other problem, viz. Closeness, which was mentioned above, one way is to declare an enumerator that stores the value for this kind of thing...

Example:

enum Distance
{
DISTANCE_VERY_CLOSE = 1,
DISTANCE_CLOSE,
DISTANCE_RELATIVELY_CLOSE,
DISTANCE_RELATIVELY_FAR,
DISTANCE_FAR,
DISTANCE_VERY_FAR,
DISTANCE_EXTREMELY_FAR
};

Then this enumerator will keep track of the distance for you, so you just need to use this macro to convert an integer to Distance (The enumerator)...

#define TO_DISTANCE(distance) ((distance) > 7 ? Distance(7) : Distance(distance))

This is a simple macro that just simply casts an integer to the enumerator and casts the digit 7 if the distance is more than 7 (Hence, DISTANCE_EXTREMELY_FAR). However, you can go ahead and add more inside the enumerator if you want. (Just remember to change 7 to the value the last enum member has)

Example use of the above method:

int main()
{
auto const dist = TO_DISTANCE(get_distance(std::make_pair(20, 20), std::make_pair(30, 30)));
accuracy *= dist; // Multiplying accuracy to distance (Hence, increases)
// Note: The accuracy needs to be at least 1 or more for this to work...
// You can check the "closeness" like this...
if (dist == DISTANCE_FAR)
std::cout << "They are far away from each other" << std::endl;
// Some other code goes here ...
return 0;
}

Kind regards,

Ruks.

How to change node positions in networkx graph?

You can pass the position dictionary (keys are nodes, values are 2-d coordinates) to the more general draw_networkx function using the pos argument:

nx.draw_networkx(G,pos= positions,with_labels=True,node_color=node_color,node_size=500)

Note that the nx.draw_shell will layout your network according to a shell layout algorithm.

Drawing nodes of multigraph in fixed position

You can set the attributes before you convert the graph to a Pydot object:

import networkx as nx                                                                                     
graph= nx.MultiGraph()

#add 4 nodes in the vertexs of a square. X and Y are the coordinates
graph.add_node(1,x=100,y=100)
graph.add_node(2,x=100,y=200)
graph.add_node(3,x=200,y=100)
graph.add_node(4,x=200,y=200)
graph.add_edge(1,2)
graph.add_edge(2,3)
graph.add_edge(3,4)
graph.add_edge(4,1)
# assign positions
for n in graph:
graph.node[n]['pos'] = '"%d,%d"'%(graph.node[n]['x'], graph.node[n]['y'])
p = nx.to_pydot(graph)
print p.to_string()
p.write('foo.dot')
# run neato -n2 -Tpng foo.dot >foo.png

The output is:

graph G {
1 [y=100, x=100, pos="100,100"];
2 [y=200, x=100, pos="100,200"];
3 [y=100, x=200, pos="200,100"];
4 [y=200, x=200, pos="200,200"];
1 -- 2 [key=0];
1 -- 4 [key=0];
2 -- 3 [key=0];
3 -- 4 [key=0];
}

Run
neato -n2 -Tpng foo.dot >foo.png
(the -n2 keeps your node positions)

Sample Image



Related Topics



Leave a reply



Submit