Рубрики
Без рубрики

Редкая матрица в Python – упрощенная

В этой статье мы посмотрим на структуру данных, которая используется для реализации редкой матрицы в Python. Давайте начнем.

Автор оригинала: Pankaj Kumar.

Редкая матрица в Python – упрощенная

В этой статье мы посмотрим на структуру данных, которая используется для реализации редкой матрицы в Python. Давайте начнем.

Что такое редкая матрица?

Редкая матрица – это матрица типа, которая имеет много нулевых элементов. То есть большинство предметов в редкой матрице являются нулями, отсюда и именем, и поэтому большинство памяти, занятых редкой матрицей, представляет собой Zeroes. Например, следующая матрица представляет собой редкую матрицу:

A = [
    [0, 4, 0, 0],
    [2, 0, 0, 5],
    [0, 0, 0, 0],
    [0, 0, 0, 1]
]

Как видите, за исключением четырех предметов, остальные являются нулями, и эти избыточные нули занимают много места в памяти.

Редкая матрица – это оптимизированный способ хранения таких матриц. По сути, это заказанный список предметов, которые не являются нулями. Каждая строка в редкой матрице хранит строку и столбец ненулевого элемента, а также сам ненулевой элемент.

Итак, для вышеуказанного матрицы A, это редкий аналог будет выглядеть так:

A = [
    [0, 1, 4],
    [1, 0, 2],
    [1, 3, 5],
    [3, 3, 1]
]

В первом ряду элементы составляют 0, 1 и 4, поэтому пункт 4 находится на индексе 0, 1. Аналогично, 2 находится на индексе 1, 0; и т.п.

Понятно, что эта версия занимает меньше места, чем обычная версия, и в случае огромной матрицы, редкая матрица берет значительно меньше места.

Чтобы использовать эту матрицу в качестве редкой матрицы, нам нужно реализовать его в классе и определять методы ввода, печати, добавления, вычитания, умножения и т. Д.

Редкая матрица в Python

Давайте посмотрим на определение класса редкой матрицы в Python.

class Sparse:
    def __init__(self, rows, columns):
        self._matrix = []
        self._num = 0
        self._rows = rows
        self._columns = columns
        
    def __repr__(self):
        prnt = f"Shape: {self._rows} x {self._columns}\n"
        for lst in self._matrix:
            prnt += lst.__repr__() + '\n'
        prnt += f"Total: {self._num}"
        return prnt
        
    def insert(self, row, column, value):
        if row < 0 | column < 0 | row >= self._rows | column >= self._columns:
            raise ValueError("Invalid row or column")
            
        if(value == 0):
            raise ValueError("Zeroes are not included in a sparse matrix")
        
        filled = False
        for i in range(self._num):
            if(self._matrix[i][0] < row):
                continue
            elif(self._matrix[i][0] > row):
                self._matrix.insert(i, [row, column, value])
                self._num += 1
                filled = True
                break
            elif(self._matrix[i][1] < column):
                continue
            elif(self._matrix[i][1] > column):
                self._matrix.insert(i, [row, column, value])
                self._num += 1
                filled = True
                break
            else:
                raise ValueError("The position is already filled")
        if(filled == False):
            self._matrix.append([row, column, value])
            self._num += 1
        return
    
    def remove(self, row, column):
        if row < 0 | column < 0 | row >= self._rows | column >= self._columns:
            raise ValueError("Invalid row or column")
            
        for i in range(num):
            if(self._matrix[i][0] == row | self._matrix[i][1] == column):
                return pop(i)
        return None
    
    def size(self):
        return self._num
    
    def shape(self):
        return tuple((self._rows, self._columns))
    
    def display(self):
        print(self)
    
    def add(self, obj):
        if(isinstance(obj, Sparse) != True):
            raise TypeError("add() method needs an object of type Sparse")
        
        if(self.shape() == obj.shape()):
            result = Sparse(self._rows, self._columns)
        else:
            raise ValueError("Invalid row or columns")
        
        i = 0
        j = 0
        k = 0
        while((i < self._num) & (j < obj._num)):
            if(self._matrix[i][0] < obj._matrix[j][0]):
                result._matrix.insert(k, self._matrix[i])
                k += 1
                i += 1
            elif(self._matrix[i][0] > obj._matrix[j][0]):
                result._matrix.insert(k, obj._matrix[j])
                k += 1
                j += 1
            elif(self._matrix[i][1] < obj._matrix[j][1]):
                result._matrix.insert(k, self._matrix[i])
                k += 1
                i += 1
            elif(self._matrix[i][1] > obj._matrix[j][1]):
                result._matrix.insert(k, obj._matrix[j])
                k += 1
                j += 1
            else:
                result._matrix.insert(k, list([self._matrix[i][0], self._matrix[i][1], self._matrix[i][2] + obj._matrix[j][2]]))
                k += 1
                i += 1
                j += 1
        while(i < self._num):
            result._matrix.insert(k, self._matrix[i])
            k += 1
            i += 1
        while(j < obj._num):
            result._matrix.insert(k, obj._matrix[j])
            k += 1
            j += 1
            
        result._num = k
        return result
    
    def fast_transpose(self):
        occurrence = []
        index = []
        
        for i in range(self._columns):
            occurrence.append(0)
        for i in range(self._num):
            occurrence[self._matrix[i][1]] += 1
        
        index.append(0)
        for i in range(1, self._columns):
            index.append(index[i-1] + occurrence[i-1])
            
        result = Sparse(self._columns, self._rows)
        result._num = self._num
        for i in range(self._num): result._matrix.append(list())
        for i in range(self._num):
            result._matrix[index[self._matrix[i][1]]] = list([self._matrix[i][1], self._matrix[i][0], self._matrix[i][2]])
            index[self._matrix[i][1]] += 1
        return result

Вышеуказанное определение довольно большое, поэтому мы посмотрим на каждую функцию один на одну:

1. Метод __init__

Для каждой редкой матрицы нам требуется изначально количество строк и столбцов, которое передается конструктору, который создает пустую редкую матрицу.

2. Метод __repr__

Это вернет строка это будет напечатано на строке, когда Печать () вызывается на объекте. В нашем случае мы печатаем форму и размер матрицы, а также фактическую редкую матрицу.

3. Вставка и удаление в редкой матрице

Чтобы вставить ненулевой элемент в определенную позицию, мы просто проходим через матрицу, чтобы найти правильное положение нового элемента и вставить его там. Сначала сравниваем ряд, а затем, если мы обнаружим, что строки совпадают, мы сравниваем столбец. Один из них должен быть другим, иначе мы поднимаем исключение.

Прежде чем делать все это, нам нужно проверить вход, заданный элемент не должен быть нулевым, а позиции должны находиться внутри матрицы.

Чтобы удалить элемент в заданном положении, процедура так же просто, как нахождение позиции в матрице и выскакивает всю строку.

4. Добавление двух разреженных матриц

Добавление двух разреженных матриц очень похоже на объединение двух сортировков списков.

Два матрицам являются в основном списки, которые содержат другие списки, которые представляют строки. И эти внутренние списки сортируются в том смысле, что первые и второе элементы каждого списка (индекс строки и столбца каждого значения) расположены в порядке возрастания.

Мы создаем три индекса: i , j , и k .

  • Я Является ли индекс следующего пункта в первой матрице.
  • J Является ли индекс следующего элемента во второй матрице.
  • к Является ли индекс следующего пункта в матрице результата.

Затем мы сравним Я Точкой в первой матрице и J «Тю элемент во второй матрице. Какой бы элемент должен быть впервые на основе индекса его строки и столбца вставляется в матрицу результата, и мы увеличиваем соответствующие индексы.

Если оба пункта имеют одинаковый показатель строки и столбца, то, безусловно, они должны быть добавлены вместе, и как только мы сделаем это, их сумма вставлена в матрицу результата.

В конце концов, один из входных матриц будет завершен, на данный момент мы просто вставляем все элементы из другой матрицы в матрицу результата, и у нас будет сумма двух матриц.

5. Быстрый транспонимент редкой матрицы

Транспонирование редкой матрицы достаточно проста, нам просто нужно поменять значения строки и столбцов, а затем сортировать строки в редкой матрице. Но такая операция очень неэффективна, и способ построена редкая матрица, у нас гораздо бывший способ транспонировать эту матрицу.

Сначала мы создадим два списка, которые помогут в алгоритме.

Первый список называется возникновение , и он будет хранить количество раз, когда каждый индекс столбца появляется в редкой матрице. Итак, это размер будет размером столбец редкой матрицы, и каждый индекс будет представлять этот столбец. Изначально он будет наполнен нулями, а позже мы будем проходить через редкую матрицу и искать значения столбца каждого элемента, и мы увеличим этот индекс в возникновение список.

Второй список называется индекс список. В этом списке мы будем хранить полученный индекс каждого элемента в исходной редкой матрице, когда она преобразуется в редкую матрицу. Итак, индекс [я] будет иметь новый индекс первого элемента с индексом столбцов Я в оригинальной матрице. Для этого мы впервые храням 0 при индексе [0], что означает, что первый элемент с индексом столбца 0 в исходной матрице будет проходить в индексе 0′-в матрице Transpose. Затем рассчитать индекс [я] Мы добавляем Индекс [I-1] и возникновение [I-1] Отказ

После этого мы смотрим на каждый элемент в редкой матрице, мы находим индекс столбца элемента, мы ищем значение в индекс Список в этом индексе, и мы используем это значение как новый индекс в матрице транспонирования. После этого мы увеличиваем значение индекса, которое мы использовали, чтобы следующий элемент с тем же индексом столбца перейдут к следующему индексу в транспонировании.

Делать это, мы можем транспонировать редкую матрицу очень эффективно.

Выход

Во-первых, мы создаем два редких матрица:

Редкий пример 1.

Теперь мы делаем дополнение и быстрые операции транспонирования:

Редкий пример 2.

Заключение

В случаях, когда матрицы в основном заполняются нулями, редкие матрицы используют гораздо меньше хранения и гораздо более эффективны. Мы обсудили, что это такое, как их создавать, а затем их реализовать, и, наконец, мы подтвердили, что с выводом мы получаем, запустив наш код.