python

Клон NumPy

  • четверг, 28 ноября 2019 г. в 00:25:28
https://habr.com/ru/post/477308/
  • Python
  • Программирование
  • Математика


image

Небольшой модуль для работы с массивами в Python без использования сторонних библиотек (клон NumPy, но только на чистом Python).

Домашним заданием в университете задали написать программу, которая вычисляет нормы и разложения матрицы, но запретили использовать сторонние библиотеки. В выборе языка программирования не ограничивали. Я выбрал python (что было ошибкой, т.к. он намного медленнее Java и C/C++) и соответственно мне нельзя использовать NumPy. В процессе пришлось написать функции выполнения операций с массивами, функции нахождения миноров, определителя и тд. В итоге получилась мини библиотека для работы с массивами.

Мой код, написанный на чистом питоне намного медленнее NumPy, который производит вычисления на C и Fortran (плюс мой код не оптимизирован).

Что может МатЛОЛ:

  • Сумма, разность и произведение матриц
  • Произведение матрицы на число
  • Транспонирование матрицы
  • Минора матрицы
  • Определитель матрицы
  • Обратная матрица
  • Союзная матрица
  • Число обусловленности матрицы
  • Первая, вторая (не доработана), Евклидова и бесконечная нормы матрицы
  • Решение уравнения AX = B
  • LU разложение
  • Разложение Холецкого
  • Метод Зейделя

Примеры использования MathLOL


Импортируем модуль:

# from mathlol import *
from mathlol import mathlol

Инициализация матрицы

matrix = mathlol()
matrix.set([[1, 2, 3],
           [4, 5, 6],
           [7, -8, 9]])
matrix.get() # Возвращает матрицу

Некоторые операции с матрицами

matrix * 2 # Произведение элементов матрицы на 2

A = [[0, 0, 0],
    [0, 1, 0],
    [0, 0, 0]]

# Произведение 2 матриц
matrix.dot(A)
matrix * A

matrix.transposition() # Транспонирование матрицы
matrix.minor(i = 0, j = 0) # Минор матрицы
matrix.determinant() # Определитель матрицы
matrix.inverse() # Обратная матрица

L, U = matrix.lu() # LU разложение
matrix.seidel(b = [[5.0], [9.0], [1.0]]) # Метод Зейделя

Так же есть функции для работы с векторами

vector = mathlol()
vector.set([1, 2, 3, 4, 5])

vector.checkvector() # Проверяет, является ли матрица вектором

vector.norm1_vector()
vector.norm2_vector()
vector.norm3_vector()

Другие примеры

Производительность MathLOL


Посмотрим скорость вычислений произведений матриц размера NxN. Матрицы заполнены рандомными целыми числами от -100 до 100.

Код
from mathlol import mathlol

import time
import random
import matplotlib.pyplot as plt

# Создаём набор данных
data = {}
for i in range(10, 110, 10):
    array = []
    for i_ in range(i):
        temp = []
        for j_ in range(i):
            temp.append(random.randint(-100, 100))
        array.append(temp)
    data[i] = array

# Производим вычисления и измеряем скорость
mlol_dot = {}
for key in data.keys():
    matrix = mathlol()
    matrix.set(matrix = data[key])
    
    start = time.process_time()
    result = matrix * matrix
    end = time.process_time() - start
    
    mlol_dot[key] = end

# Строим график
plt.plot(mlol_dot.keys(), mlol_dot.values())

plt.title("MathLOL \nПроизведение матриц")

plt.xlabel("Размер матрицы (NxN)")
plt.ylabel("Время (сек)")


image

Скорость вычисления произведений матриц размера от 100x100 до 1000x1000

image

Сравним скорости вычислений numpy и mathlol. К сожалению, mathlol очень сильно уступал в скорости и я решил взять для numpy матрицы размеров от 100x100 до 1000x1000, а для mathlol от 10x10 до 100x100.

image

MathLOL вычислил произведение матрицы 100x100 на саму себя за 0.16 секунды, а NumPy вычислил произведение матрицы 1000x1000 на саму себя за 0.002 (!!!) секунды. Разница просто огромная.

У нас стояла задача просто реализовать различные функции для работы с матрицами, что мы и сделали, но программа с большими матрицами работает не так быстро как хотелось бы. Осталось доработать программу, добавить еще несколько функций (например, функция для вычисления числа Тодда), буду признателен если посмотрите код, укажете на ошибки и возможно поможете доработать код.

На этом все, код и примеры выложены на гитхабе.

P.S. В процессе написания статьи мне захотелось поэкспериментировать и встроить в свой модуль C/C++. Займусь этим в ближайшее время и посмотрим насколько удастся приблизиться к производительности NumPy.