Just a style question: Is there a build-in method to get the combinations under the assertion of commutative property and excluding elements paired with itself?
I don't think this is the most self-explanatory way to do it so I wouldn't recommend it but I'll include it for completeness.
Uses the fact that the commutative pairs are the upper and lower triangles of the matrix produced by the product of both arrays.
The numpy function np.tril_indices returns a tuple containing the indices for only the lower-triangle of an array.
>>> import numpy as np
>>> n_vars = len(a)
>>> assert len(b) == n_vars # Only works if len(a) == len(b)
>>> [(a[i], b[j]) for i, j in zip(*np.tril_indices(n_vars))]
[('1', '1'), ('2', '1'), ('2', '2'), ('3', '1'), ('3', '2'), ('3', '3')]
>>> [(a[i], b[j]) for i, j in zip(*np.tril_indices(n_vars, k=-1))]
[('2', '1'), ('3', '1'), ('3', '2')]
The k argument in np.tril_indices is an offset parameter so k=-1 means it doesn't include the diagonal terms.
Since it's a numpy function it's probably very fast.
a and b to numpy arrays you can also do this:>>> a = np.array(a)
>>> b = np.array(b)
>>> ind = np.tril_indices(n_vars, k=-1)
>>> list(zip(a[ind[0]], b[ind[1]]))
[('2', '1'), ('3', '1'), ('3', '2')]
>>> np.stack([a[ind[0]], b[ind[1]]]).T
array([['2', '1'],
['3', '1'],
['3', '2']], dtype='