I've been trying to reduce the indentation from a method in my code. The solution will probably be unrelated to the language, in this case python, although it may rely on some python specific libraries e.g. itertools.
The code below is part of this implementation of Kruskal's algorithm.
def generate_diff(self, ndarr, arr): """ Internal method to calculate the difference between all points """ l = ndarr.shape pij = np.empty((l,l,)) * np.nan pijm = np.empty((l,l,l)) * np.nan for i in range(l): for j in range(l): if i != j: pij[i, j] = self.pcor_squared(np.array([ndarr[:,i], arr, ndarr[:,j]])) for m in range(l): if m != i and m != j and m > j: pijm[m, i, j] = self.pcor_squared(np.array([ndarr[:,i], arr, ndarr[:,j], ndarr[:, m]])) return (l, pij, pijm)
As you can see it's looping through the length of the shape 3 times! (in creating i, j, m).
arr are just a two dimensional numpy array and a one dimensional numpy array. The specs in the file will enable you to hit the method very quickly if you add an
assert False and a run
py.test --pdb from the command.
I've tried changing the first line to
for i, j in it.combinations(range(l), 2): and doing both sides of the square of the matrix simulataneously with:
pij[i, j] = self.pcor_squared(np.array([ndarr[:,i], arr, ndarr[:,j]])) pij[j, i] = self.pcor_squared(np.array([ndarr[:,j], arr, ndarr[:,i]]))
but it's a bit off (i.e. gives wrong numbers in the spec).
In short I'm trying to reduce the complexity by making the code linear and hopefully making it more performant by removing the looping. A better understanding of matrices may be key to this.