Home > Net >  Find a (partial) list of matrix unity roots
Find a (partial) list of matrix unity roots

Time:11-07

I am looking for a way to build a list of matrix square roots of 1 and -1. Only interested in dimensions 2 to 4, and I don't even need a complete set, just a practical usable one (meaning I could stop the loop at some point). Here's my (very) inefficient solution

def racines(n, dim, field='real'):
    if field == 'real':
        unites = [1, 0, -1]
    elif field == 'complex':
        unites = [1, 0, -1, 1j, -1j]
    if dim == 2:
        liste = [np.array([[a,b], [c,d]]) for a in unites
                 for b in unites for c in unites 
                 for d in unites]
    elif dim == 3:
        liste = [np.array([[a, b, c], [d, e, f], [g, h, i]])
                 for a in unites for b in unites for c in unites 
                 for d in unites for e in unites for f in unites
                 for g in unites for h in unites for i in unites]
    elif dim == 4:
        liste = [np.array([[a,b,c,d], [e,f,g,h], [i,j,k,l], [m,o,p,q]])
                 for a in unites for b in unites for c in unites for d in unites
                 for e in unites for f in unites for g in unites for h in unites
                 for i in unites for j in unites for k in unites for l in unites
                 for m in unites for o in unites for p in unites for q in unites]
    liste = [m for m in liste if np.linalg.det(m) != 0]
    liste = [m for m in liste if np.array_equal(np.matmul(m, m), np.identity(dim, dtype='int')*n)]
return(liste)

Works well until 4d where of course it becomes too much to handle... How to make it faster ?

CodePudding user response:

You can do it recursively. For exemple if I want the lists of n numbers between 0 and 4 you could use

def get_lists(size, max_it, accumulator = [], lists = []):
    if size ==0:
        lists.append(accumulator)
    else:
        for i in range(5):
            if len(lists) == max_it:
                break
            l = accumulator.copy()
            l.append(i)
            get_lists(size-1,max_it, l, lists)

            
def lists(size,max_it=-1):
    l = []  
    get_lists(size,max_it, [], l)
    return l        
print(lists(3,10))

with max_it the amount of different list you want (set to -1 if you want them all)

CodePudding user response:

For those who would need it, here's what did the trick. Still not pretty, but it works a lot faster in 4d

def racines(n, dim, field='real'):
    unites = [1, 0, -1]
    if field == 'complex':
        unites  = [1j, -1j]
    elif field != 'real':
        print('Unknown field !')
        return([])
    if dim == 2:
        liste = [np.array([[a,b], [c,d]]) for a in unites
                 for b in unites for c in unites 
                 for d in unites]
    elif dim == 3:
        liste = [np.array([[a, b, c], [d, e, f], [g, h, i]])
                 for a in unites for b in unites for c in unites 
                 for d in unites for e in unites for f in unites
                 for g in unites for h in unites for i in unites]
    elif dim == 4:
        roots_2d = racines(n, 2, field=field)
        neg_roots_2d = racines(-n, 2, field=field)
        other = [np.identity(2, dtype='int'), np.identity(2, dtype='int')*-1, np.zeros([2,2], dtype='int')]
        unites = roots_2d   neg_roots_2d   other
        liste = [np.hstack([np.vstack([a,b]), np.vstack([c,d])])
                 for a in unites for b in unites for c in unites for d in unites]
    else:
        print('No can do !')
        return([])
    liste = [m for m in liste if np.linalg.det(m) != 0]
    liste = [m for m in liste if np.array_equal(np.matmul(m, m), np.identity(dim, dtype='int')*n)]
    return(liste)
# res = racines(1, 4, field='real') # 2.43s
# res = racines(1, 4, field='complex') # 2min 18s
  • Related