Left/right rotation of BST infinite loop between two unsatisfactory solutions? - python

I don't know my algorithms too well, so I'm probably missing something really basic. It seems to me that a standard rotate-left/rotate-right implementation (I'm looking at this link from Interactive Python) on this tree (called any time the balancing factor is not -1, 0, 1) will get into an infinite loop because the balancing factor will always be -2 or +2. Am I missing something or is this the correct conclusion? I'm pasting sample code at the bottom showing rotateLeft as implemented in the link I pasted
def rotateLeft(self,rotRoot):
newRoot = rotRoot.rightChild
rotRoot.rightChild = newRoot.leftChild
if newRoot.leftChild != None:
newRoot.leftChild.parent = rotRoot
newRoot.parent = rotRoot.parent
if rotRoot.isRoot():
self.root = newRoot
else:
if rotRoot.isLeftChild():
rotRoot.parent.leftChild = newRoot
else:
rotRoot.parent.rightChild = newRoot
newRoot.leftChild = rotRoot
rotRoot.parent = newRoot
rotRoot.balanceFactor = rotRoot.balanceFactor + 1 - min(newRoot.balanceFactor, 0)
newRoot.balanceFactor = newRoot.balanceFactor + 1 + max(rotRoot.balanceFactor, 0)
Does this avoid an infinite loop (with its complementary rotateRight), and if so, how?

From my understanding of balancing BST's is that you not only have a left/right rotate, but instead you have 4 types of shifts. A left,left rotate (similar to right right), and a right-left rotate(similar to left-right).
I may be wrong at least this is the algorithm I had to write. Where the directions of left and right represent where you traveled the last 2 steps of the tree to find your insertion point.
You may want to look into AVL tree's as this seems like the type of problem you are trying to solve.

Related

Rat with the randomize path in and 2-D array

The problem is similar to rat-maze problem. I have given an 2-d array MxN. each cell of an array is either 1 or 0 ,where 1 means blocked. I have given 2 points (starting point and ending point). I have to go from start index to end index. But the catch is 1) Path should be random. 2) There should be some parameter which allow me to decide how much random it can be. (i.e how crazily it should wander before reaching to its destination.) 3) Path should not intersect itself.(like a snake game).
This algorithm is needed to create population (randomly) which will used as input for genetic model for further optimize it.
For now i have used bfs and created one solution. But the problem is i cannot create any no of random path with this (which i will later use as population) + i'm unable to formalize the idea of how much random it should be.
This is my code that only produces min path by using bfs
def isSafe(x,y,length):
if ((x<length) and (x>-1) and (y<length) and (y>-1)):
return True;
return False;
def path(room,x1,y1,x2,y2,distance):
roomSize=len(room);
if ((x1==x2) and (y1==y2)):
room[x1][y1]=distance+1
return
queue=[[x1,y1]]
room[x1][y1]=0
start=0
end=0
while start<=end:
x,y=queue[start]
start+=1
distance=room[x][y]
for i in [-1,1]:
if isSafe(x+i,y,roomSize):
if room[x+i][y]=="O":
queue.append([x+i,y])
room[x+i][y]=distance+1
end+=1;
for i in [-1,1]:
if isSafe(x,y+i,roomSize):
if room[x][y+i]=="O":
queue.append([x,y+i])
room[x][y+i]=distance+1
end+=1;
def retrace(array,x1,y1,x2,y2):
roomSize=len(array)
if not (isSafe(x2,y2,roomSize)):
print("Wrong Traversing Point");
if type(array[x2][y2])==str:
print("##################No Pipe been installed due to path constrained################")
return [];
distance=array[x2][y2];
path=[[x2,y2]]
x=0
while not (array[x2][y2]==0):
if ((isSafe(x2+1,y2,roomSize)) and type(array[x2+1][y2])==int and array[x2+1][y2]==array[x2][y2]-1):
x2+=1;
path.append([x2,y2]);
elif ((isSafe(x2-1,y2,roomSize)) and type(array[x2-1][y2])==int and array[x2-1][y2]==array[x2][y2]-1):
x2-=1;
path.append([x2,y2])
elif ((isSafe(x2,y2+1,roomSize)) and type(array[x2][y2+1])==int and array[x2][y2+1]==array[x2][y2]-1):
y2+=1;
path.append([x2,y2]);
elif ((isSafe(x2,y2-1,roomSize)) and type(array[x2][y2-1])==int and array[x2][y2-1]==array[x2][y2]-1):
y2-=1;
path.append([x2,y2]);
return path;

Random ultrametric trees

I've implemented a program on python which generates random binary trees. So now I'd like to assign to each internal node of the tree a distance to make it ultrametric. Then, the distance between the root and any leaves must be the same. If a node is a leaf then the distance is null. Here is a node :
class Node() :
def __init__(self, G = None , D = None) :
self.id = ""
self.distG = 0
self.distD = 0
self.G = G
self.D = D
self.parent = None
My idea is to set the distance h at the beginning and to decrease it as an internal node is found but its working only on the left side.
def lgBrancheRand(self, h) :
self.distD = h
self.distG = h
hrandomD = round(np.random.uniform(0,h),3)
hrandomG = round(np.random.uniform(0,h),3)
if self.D.D is not None :
self.D.distD = hrandomD
self.distD = round(h-hrandomD,3)
lgBrancheRand(self.D,hrandomD)
if self.G.G is not None :
self.G.distG = hrandomG
self.distG = round(h-hrandomG,3)
lgBrancheRand(self.G,hrandomG)
In summary, you would create random matrices and apply UPGMA to each.
More complete answer below
Simply use the UPGMA algorithm. This is a clustering algorithm used to resolve a pairwise matrix.
You take the total genetic distance between two pairs of "taxa" (technically OTUs) and divide it by two. You assign the closest members of the pairwise matrix as the first 'node'. Reformat the matrix so these two pairs are combined into a single group ('removed') and find the next 'nearest neighbor' ad infinitum. I suspect R 'ape' will have a ultrametric algorhithm which will save you from programming. I see that you are using Python, so BioPython MIGHT have this (big MIGHT), personally I would pipe this through a precompiled C program and collect the results via paup that sort of thing. I'm not going to write code, because I prefer Perl and get flamed if any Perl code appears in a Python question (the Empire has established).
Anyway you will find this algorhithm produces a perfect ultrametric tree. Purests do not like ultrametric trees derived throught this sort of algorithm. However, in your calculation it could be useful because you could find the phylogeny from real data , which is most "clock-like" against the null distribution you are producing. In this context it would be cool.
You might prefer to raise the question on bioinformatics stackexchange.

Can't implement GJK distance algorithm

I'm trying to design my own physics engine from scratch, as well as the vector/matrix libraries.
Everything worked beautifully so far, until I tried to implement collision detection in my library. First with SAT, worked great for detecting, but I wanted to find the distance between the objects as well. Then I tried to implement the GJK distance algorithm, just to see if I can find the distance between the origin and a polygon. But it just doesn't work, the smallest distance perceived by the algorithm that I implemented was one of the vertex of the polygon:
I know I made the other libraries from scratch, but I'm positive that they are working. Anyways, here's the code where I've implemented the GJK:
#objectL[0] is a hexagon
v = objectL[0].nodes[0]
W = []
u = 0
close_enough = False
while not close_enough and v != Vector(0,0):
w = objectL[0].support(-v)
d = v*w/abs(v) #*:dot product abs:magnitude
u = max(u,d)
close_enough = abs(v) - u <= 0.0001
if not close_enough:
W.append(w)
while len(W)>2:
del W[0]
v = Vector(0,0).vectorToLine(*W) #distance from the origin to the simplex
#formed by W
And now the support method:
def support(self,axis):
maxP = self.nodes[0]*axis #dot product of first vertex with the axis
n = self.nodes[0]
for node in self.nodes[1:]:
p = node*axis
if p>maxP:
maxP = p
n = node
return node
Those are the code snippets, that I think is where the error is, but I can't find it. The GJK algorithm I've copied from here. Thanks!
Edit:
Here is my project(implemented in pygame)
Ok, found the error. Which wasn't on the implementation, but rather on the functions that I've previously made: the support, which returned node instead of n and the vectorToLine function which returned an incorrect vector(negative value).
Also for those that are reading this post years from now, and trying to implement this algorithm, please note that I only changed the while len(W)>2 part to:
while len(W)>2:
maxD = 0
for w in W:
if abs(w)>maxD:
maxD = w
W.remove(maxD)
Which removes the farthest point of the simplex/triangle, so it gets the two closest point(to the origin) to continue the algorithm.

Batch-constraining objects (feathers to a wing)

really not long ago I had my first dumb question answered here so... there I am again, with a hopefully less dumb and more interesting headscratcher. Keep in my mind I am still making my baby steps in scripting !
There it is : I need to rig a feathered wing, and I already have all the feathers in place. I thought of mimicking another rig I animated recently that had the feathers point-constrained to the arm and forearm, and orient-constrained to three other controllers on the arm : each and every feather was constrained to two of those controllers at a time, and the constraint's weights would shift as you went down the forearm towards the wrist, so that one feather perfectly at mid-distance between the elbow and the forearm would be equally constrained by both controllers... you get the picture.
My reasoning was as follows : let's make a loop that iterates over every feather, gets its world position, finds the distance from that feather to each of the orient controllers (through Pythagoras), normalize that and feed the values into the weight attribute of an orient constraint. I could even go the extra mile and pass the normalized distance through a sine function to get a nice easing into the feathers' silhouette.
My pseudo-code is ugly and broken, but it's a try. My issues are inlined.
Second try !
It works now, but only on active object, instead of the whole selection. What could be happening ?
import maya.cmds as cmds
# find world space position of targets
base_pos = cmds.xform('base',q=1,ws=1,rp=1)
tip_pos = cmds.xform('tip',q=1,ws=1,rp=1)
def relative_dist_from_pos(pos, ref):
# vector substract to get relative pos
pos_from_ref = [m - n for m, n in zip(pos, ref)]
# pythagoras to get distance from vector
dist_from_ref = (pos_from_ref[0]**2 + pos_from_ref[1]**2 + pos_from_ref[2]**2)**.5
return dist_from_ref
def weight_from_dist(dist_from_base, dist_to_tip):
normalize_fac = (1/(dist_from_base + dist_to_tip))
dist_from_base *= normalize_fac
dist_to_tip *= normalize_fac
return dist_from_base, dist_to_tip
sel = cmds.ls(selection=True)
for obj in sel:
# find world space pos of feather
feather_pos = cmds.xform(obj, q=1, ws=1, rp=1)
# call relative_dist_from_pos
dist_from_base = relative_dist_from_pos(feather_pos, base_pos)
dist_to_tip = relative_dist_from_pos(feather_pos, tip_pos)
# normalize distances
weight_from_dist(dist_from_base, dist_to_tip)
# constrain the feather - weights are inverted
# because the smaller the distance, the stronger the constraint
cmds.orientConstraint('base', obj, w=dist_to_tip)
cmds.orientConstraint('tip', obj, w=dist_from_base)
There you are. Any pointers are appreciated.
Have a good night,
Hadriscus

Graph-tool edge_property to string

I've got a graph with edge weights. I looked around and found that I can use edge_properties to represent an edge weight. I do it like this:
edge_weight = g.new_edge_property("double")
for i in range(10):
e = g.add_edge(i, i+1)
edge_weight[e] = i
Now I want to print a graph from this with the given edge weights on the edges. Do you have any ideas how to do this? The only thing that I could come up is this:
edge_weight = g.new_edge_property("double")
edge_str_weight = g.new_edge_property("string")
for i in range(10):
e = g.add_edge(i, i+1)
edge_weight[e] = i
edge_str_weight[e] = str(i)
graph_draw(g, edge_text=edge_str_weight, output="out.png")
It works, but it's quite redundant. Also if it's suggested to store the edge weight in an other structure or something, feel free to comment :)
In principle, there is no need create a different property, since a conversion to string will be made inside graph_draw(). However, graph-tool uses hexadecimal float notation by default, because it allows for a perfect representation. This is ideal for storing the values in a file, but not for displaying them. Therefore your approach is correct. You can perhaps do it more succinctly and efficiently using map_property_values():
label = g.new_edge_property()
map_property_values(edge_weight, label, lambda w: str(w))
graph_draw(g, edge_text=label, output="out.png"))
Maybe it's a typo but the assignment to edge_str_weight should reference the edge e you are currently working with:
edge_str_weight[e] = str(i)
Other than that, working with property maps is generally the best option with graph-tool. If for some reason you want to use a one-time property-map just for plotting purposes, you will again need to create one:
edge_alt_str_weights = g.new_edge_property("string")
for edge in g.edges():
edge_alt_str_weights[edge] = str(edge_weight[edge])
You might also want to define the property maps you plan to keep around as internal in case you want to use them persistently.

Categories

Resources