networkx merging graph ram issue - python

I'm quite a newbie with networkx and it seems that i'm having RAM issues when running a function that merges two different graphs. This function adds up the weight of edges that are common to both graphs.
I have a list of 8~9 graphs each containing about 1000-2000 nodes which I merge in this loop:
FinalGraph = nx.Graph()
while len(graphs_list)!=0:
FinalGraph = merge_graphs(FinalGraph,graphs_list.pop())
using this function
def merge_graphs(graph1, graph2):
edges1 = graph1.edges
edges2 = graph2.edges
diff1 = edges1 - edges2
if diff1==edges1:
return nx.compose(graph1,graph2)
else:
common_edges = list(edges1 - diff1)
for edges in common_edges:
graph1[edges[0]][edges[1]]['weight'] += graph2[edges[0]][edges[1]]['weight']
return nx.compose(graph2, graph1)
When running my script, my computer will always freeze when reaching this loop. Am i doing some kind of bad reference cycle or something ? Am i missing something in the networkx doc more effective that could help me not use this function for my purpose ?
Thanks for reading me, I hope i'm making sense

There seems to be a lot of extra work going on here caused by you trying to check if the conditions allow you to use compose. This may be contributing to the trouble. I think it might work better to just iterate through the edges and nodes of the graph. The following looks like a more direct way to do it (and doesn't require creating as many variables, which might be contributing to the memory issues)
final_graph = nx.Graph()
for graph in graphs_list:
final_graph.add_nodes_from(graph.nodes())
for u, v, w in graph.edges(data=True):
if final_graph.has_edge(u,v):
final_graph[u][v]['weight'] += w
else:
final_graph.add_edge(u,v,weight = w)

Related

Blender to Unreal - rotation matrix to left handed

[I have been trying many solutions posted here and there, yet I cannot make this work]
I have a python script on blender side exporting object rotations like this
m = obj.matrix_world.to_euler('XYZ')
rot = mathutils.Vector((math.degrees(m.x),math.degrees(m.y),math.degrees(m.z)))
on unreal side, still in python, setting up rotators for imported objects :
def createRotator(actor_rotation):
rotatorX = unreal.MathLibrary.rotator_from_axis_and_angle(unreal.Vector(0.1,0.0,0.0),actor_rotation.x)
rotatorY = unreal.MathLibrary.rotator_from_axis_and_angle(unreal.Vector(0.0,0.1,0.0),actor_rotation.y)
rotatorZ = unreal.MathLibrary.rotator_from_axis_and_angle(unreal.Vector(0.0,0.0,0.1),actor_rotation.z)
temp = unreal.MathLibrary.compose_rotators(rotatorX,rotatorY)
rotator = unreal.MathLibrary.compose_rotators(temp,rotatorZ)
return rotator
yet the objects are not placed correctly (in term of rotation) in unreal
I tried:
adding - in front of different rotation members in blender
flipping the order of the unreal rotators are combined in unreal
tried y=z and z=-y
tried z = -z or y=-y
(I could go on since I been busting my head on this for a whole week)
I been through so many posts, every answer is different, and none of them is working
can someone more clever than I am end my misery and tell me how to solve this ?
thanks
[edit:]
I spawn the actor like this
pos = unreal.Vector(float(row["posx"]),float(row["posy"]),float(row["posz"]))
rot = unreal.Vector(float(row["rotx"]),float(row["roty"]),float(row["rotz"]))
rotator = createRotator(rot)
staticMeshActor = unreal.EditorLevelLibrary.spawn_actor_from_object(staticMesh, pos, rotator)

How to cluster a graph using python igraph

I've been using python igraph to try to make an easier time of generating and analyzing graphs. My code below generates a random graph of 50 nodes and clusters it:
from igraph import *
import random as rn
g = Graph()
size = 50
g.add_vertices(size)
vert = []
for i in range(size):
for j in range(size):
test = rn.randint(0,5)
if j >= i or test is not 0:
continue
g.add_edges([(i,j)])
#layout = g.layout("kk")
#plot(g, layout = layout)
#dend = VertexDendrogram(graph=g, optimal_count=10)
clust = VertexClustering(g, membership=range(size))
#clust = dend.as_clustering()
c = clust.cluster_graph()
plot(clust, mark_groups=True)
layout = c.layout("kk")
#plot(c, layout = layout)
However, I'm not sure if this is correct, since the result has every single node as its own, isolated cluster. I am assuming this is somehow related to membership, the required parameter of VertexClustering, because I really don't understand what it means or why it is required.
Here is what the terse documentation says:
the membership list. The length of the list must be equal to the number of vertices in the graph. If None, every vertex is assumed to belong to the same cluster.
And doesn't explain what I am supposed to set membership to in order to get a normal regular clustering.
Alternatively I tried using the VertexDendrogram as seen in the two commented lines of code. However, running this comes up with this runtime error:
Traceback (most recent call last):
File "sma_hw6_goedeke.py", line 22, in <module>
dend = VertexDendrogram(graph=g, optimal_count=10)
TypeError: __init__() takes at least 3 arguments (3 given)
This is because VertexDendrogram requires the parameter merges. However, once again I have no clue what merges is supposed to be set to or why it is required. The documentation again says almost nothing:
merges - the merges performed given in matrix form.
And I have no clue what that is. So what should I do to this code to get a normal, regular clustering for my random graph I can experiment with?
I stand by my original assessment that the documentation for igraph is maddeningly too terse.
The function I actually needed for what I am doing is igraph.Graph.community_fastgreedy(). In general, it seems all the functions that run a clustering algorithm all start with "community" in their name.

Assign cluster to each shell in an object - Maya Python

I'm quite a noob in Python.
I can write a simple script to assign a cluster to vertexes of the selected objects.
Like this:
import maya.cmds as cmds
activeSelection = cmds.ls(selection=True)
for i in activeSelection:
cmds.polyListComponentConversion( i, ff=True, tv=True, internal=True )
cmds.cluster( i, rel=True )
But it turned out I need to assign a cluster to vertexes of each individual polygon shell of the object. I've spent few hours searching and trying different scripts and trying to modify them but nothing seems to really work.
Would you guys be so kind to give a hint?
Thank you,
Anton
If you don't want to separate and then re-combine your mesh (to keep clean history, or you're restricted from modifying the geo in any way except deformers for some reason...), you could use this to "separate" your shells out non-destructively
import maya.cmds as mc
shells = []
face_count = mc.polyEvaluate(geom, f=True)
faces = set(range(face_count))
for face in xrange(face_count):
if face in faces:
shell_indices = mc.polySelect(geom, q=True, extendToShell=face)
shell_faces = ['%s.f[%d]' %(geom, i) for i in shell_indices]
shells.append(mc.polyListComponentConversion(shell_faces, toVertex=True))
faces -= set(shell_indices)
elif not faces:
break
this will give you a list where each item is a list of cps for a shell. All that's left to do is to cluster each item of the shells list
I'd try using cmds.polySeparate() to split the mesh into shells, then cluster the pieces and re-assemble them into a combo mesh. Something like this:
sel = cmds.ls(sl=True)
pieces = cmds.listRelatives(cmds.polySeparate(sel), c=True)
clusters = [cmds.cluster(p, rel=True) for p in pieces]
cmds.polyUnite(pieces)
Depending on the application you might not really need the clusters, since the polySeparate will give you one transform per shell and you'll be able to animated the original shell transforms directly while keeping the combined mesh

more efficient Python scripting in Blender3D

I am basically building a 3D scatter plot using primitive UV spheres and am running into memory issues when attempting to create more than a couple hundred points at one time. I am limited on my laptop with a 2.1Ghz processor but wanted to know if there is a better way to write this:
import bpy
import random
while count < 5:
bpy.ops.mesh.primitive_uv_sphere_add(size=.3,\
location=(random.randint(-9,9), random.randint(-9,9),\
random.randint(-9,9)), rotation=(0,0,0))
count += 1
I realize that with such a simple script any performance increase is likely negligible but wanted to give it a shot anyway.
Some possible suggestions
I would pre-calculate the x,y,z values, store them in a mathutil vector and add it to a dict to be iterated over.
Duplication should provide a smaller memory footprint than
instantiating new objects. bpy.ops.object.duplicate_move(OBJECT_OT_duplicate=(linked:false, TRANSFORM_OT_translate=(transform)
Edit:
Doing further research it appears each time a bpy.ops.* is called the redraw function . One user documentented exponential increase in time taken to genenerate UV sphere.
CoDEmanX provided the following code snippet to another user.
import bpy
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.mesh.primitive_uv_sphere_add()
sphere = bpy.context.object
for i in range(-1000, 1000, 2):
ob = sphere.copy()
ob.location.y = i
#ob.data = sphere.data.copy() # uncomment this, if you want full copies and no linked duplicates
bpy.context.scene.objects.link(ob)
bpy.context.scene.update()
Then it is just a case of adapting the code to set the object locations
obj.location = location_dict[i]

What is the easiest way to generate a Control Flow-Graph for a method in Python?

I am writing a program that tries to compare two methods. I would like to generate Control flow graphs (CFG) for all matched methods and use either a topological sort to compare the two graphs.
RPython, the translation toolchain behind PyPy, offers a way of grabbing the flow graph (in the pypy/rpython/flowspace directory of the PyPy project) for type inference.
This works quite well in most cases but generators are not supported. The result will be in SSA form, which might be good or bad, depending on what you want.
There's a Python package called staticfg which does exactly the this -- generation of control flow graphs from a piece of Python code.
For instance, putting the first quick sort Python snippet from Rosseta Code in qsort.py, the following code generates its control flow graph.
from staticfg import CFGBuilder
cfg = CFGBuilder().build_from_file('quick sort', 'qsort.py')
cfg.build_visual('qsort', 'png')
Note that it doesn't seem to understand more advanced control flow like comprehensions.
I found py2cfg has a better representation of Control Flow Graph (CFG) than one from staticfg.
https://gitlab.com/classroomcode/py2cfg
https://pypi.org/project/py2cfg/
Let's take this function in Python:
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib_gen = fib()
for _ in range(10):
next(fib_gen)
Image from StaticCFG:
Image from PY2CFG:
http://pycallgraph.slowchop.com/ looks like what you need.
Python trace module also have option --trackcalls that can be an entrypoint for call tracing machinery in stdlib.

Categories