Search code examples
pythonarraysnumpymatrixsortedlist

Sorted list of matrices ordered by their determinant in Python


I am trying to keep an ordered list of matrices where the ordering is given by the absolute value of the determinant.

To do this I thought about using the SortedKeyList object in the sortedcontainers package. My code is the following:

import numpy as np
import numpy.linalg as la
from sortedcontainers import SortedKeyList

def random_mat(n):
  return np.random.randint(0,5,n*n)

def abs_det(M):
  n = np.int(np.sqrt(len(M)))
  return np.abs(la.det(M.reshape((n,n)))

L = SortedKeyList([random_mat(3): i in range(10)], key=abs_det)

# So far this doesn't give me any issues. Updating the list is the problem:

M = np.array([0,1,2,1,0,2,2,1,0])
L.update(M) #This gives me an error

The error appears in the function abs_det, it says that it cannot take the length of an integer (numpy.int32), I suspect that when comparing arrays the sorted list is not taking the array as a whole but using the key function entrywise. Originally I tried to use the arrays as matrices with a shape (n,n) but when including them in the sorted list the shape would be lost and they were stored as arrays causing other problems when trying to compare them.

A sorted dictionary would not solve the problem as I am interested in taking ranges of the list.

What would be a way to keep a sorted list of matrices ordered by the absolute value of their determinant? Perhaps there is another implementation in Python of a sorted list that can deal with these sort of objects?


Solution

  • SortedKeyList.update is expecting an iterable, so it iterates over all the single integers in M and adds each one to the sorted container.

    From the docstring in sortedlist.py

    def update(self, iterable):
        """Update sorted list by adding all values from `iterable`.
    

    It appears to work as you intended if you change that line to

    L.update([M])
    

    The method for adding a single item is add (thanks Kelly Bundy)

    L.add(M)