简体   繁体   中英

How can I correspond multiple ‘values’ to a single key? (in a matrix diagonalization scenario)

I'm writing a code (using Python) to simultaneously diagonalize two commuting matrices A and B, and hoping to create a dictionary to do this. Here, 'keys' are the eigenvalues, and 'values' are eigenvectors (may or may not be degenerate). Here's the program I've written. However, it cannot give me all the eigenvectors with shared eigenvalue. I guess I need to change something in my code to accommodate degeneracy, but how can I do this? Thanks!

def simultaneous_eig(A, B):
epsilon = 10**-10
vals, vecs = la.eig(A)
degen = {}
for n in range(0,len(vals)):
    for m in range(0,n):
        #equality up to certain precision
        if np.abs(vals[m]-vals[n]) < epsilon:
            degen.get(vals[m], vecs[:,n])              
    degen[vals[n]] = np.array([vecs[:,n]])
return degen

I found a few issues in your function. First, to achieve the recursive comparison you are trying to make, the outer loop should go from 0 to len(vals)-1, and the inner loop should be from “n” to len(vals), as seen in my corrected snippet below.

Also, the “.get()” method for dictionaries does not modify in place. In other words, you must assign the output to a variable within the “if” clause (again, see corrected code below).

Finally, to avoid extra singleton dimensions, avoid putting “[]” around the variable you wish to convert to a numpy array.

The revised function below should solve your problems. I wasn't able to test it completely, so let me know if there are still issues.

Happy coding!

def simultaneous_eig(A, B):
    epsilon = 10**-10
    vals, vecs = la.eig(A)
    degen = {}
    for n in range(0,len(vals)-1):
        for m in range(n+1,len(vals)):
            #equality up to certain precision
            if np.abs(vals[m]-vals[n]) < epsilon:
                vecs[:,n] = degen.get(vals[m])              
        degen[vals[n]] = np.array([vecs[:,n]])
    return degen

Depending on the size of the values in your matrices, you may be using the wrong criterion for "almost equal". For example, when comparing scalars, 1E-20 and 1.1E-20 would be "almost equal" according to your criterion, but 1E20 and 1.1E20 would not be, even though the relative error is the same.

Why not just use math.isclose ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM