Единичная матрица¶
В этом скрипте мы расскажем о нескольких способах создания единичных матриц и покажем, как можно сравнить между собой эти матрицы с точки зрения занимаемой ими памяти.
Описание задачи¶
Создадим матрицу, главная диагональ которой заполнена единицами (остальные элементы либо нулевые, либо – пропуски). Допусти, что такая матрица может быть не только квадратной, а в идеале – еще и многомерной.
При помощи циклов¶
Единичную матрицу можно создать при помощи циклов следующим образом.
n = 14
m = 11
eye = zeros( m, n )
for i in 1:n
if m < n
if i <= m
eye[i,i] = 1
end
else
eye[i,i] = 1
end
end
gr()
heatmap( eye, yflip=:true, c=:Reds )
Через короткий цикл¶
Проставить единицы вдоль главной диагонали можно в сжатом цикле.
eye_array = zeros( 5, 5 );
[eye_array[ i,i ] = 1 for i in 1:minimum( size(eye_array) )];
heatmap( eye_array, yflip=:true, c=:Purples )
Такой код можно адаптировать для многомерного случая, прибегнув к функции ndims
, которая возвращает количество измерений исходной матрицы, главную диагональ которой мы наполняем единицами.
eye3D = zeros(5,4,3)
[eye3D[ repeat( [i], ndims(eye3D) )... ] = 1 for i in 1:minimum( size(eye3D) )];
display( eye3D )
Но этот пользовательский код довольно быстро станет сложно подерживать в рабочем состоянии, если требования к системе будут разрастаться. Лучше воспользоваться дополнительными библиотеками, тем более что они тоже встроены в среду Engee.
Библиотеки LinearAlgebra: объект I
¶
Наиболее экономный способ создания такой матрицы заключается в использовании команды I
.
using LinearAlgebra
I
Этот объект занимает очень мало памяти, ведет себя как единичная матрица, его можно домножать на любые объекты, а при помощи команды Matrix()
его перевести в матрицу.
Matrix( 5I, 3, 3)
Создадим прямоугольную матрицу из чисел булевского типа с единицами по главной диагонали:
Matrix{Bool}(I, 4, 10)
Создадим, для сравнения, единичную матрицу размером 5 на 5.
eye_I = Matrix{Bool}(I, 5, 5)
Библиотека LinearAlgebra: команда Diagonal
¶
Еще один интересный способ предоставляет функция Diagonal
. С ее помощью можно расположить вектор вдоль главной диагонали квадратной матрицы. Остальные элементы не хранятся в памяти, матрица отображается как разреженный массив (SparseArray
).
using LinearAlgebra
eye_Diagonal = Diagonal( repeat([1], 5) )
Библиотека LinearAlgebra: функция diagm
¶
Еще одна функция позволяет расположить векторы вдоль любой диагонали матрицы, не только главной.
eye_diagm = diagm( 0 => repeat([1], 5) )
Визуализируем эту матрицу:
heatmap( diagm( 0 => repeat([1], 5), 3=>repeat([1], 5) ), yflip=:true, c=:Blues )
Библиотека SparseArrays¶
Построить единичную разреженную матрицу напрямую средствами библиотеки SparseArrays
можно следующим образом:
using SparseArrays: spdiagm
eye_spdiagm = spdiagm(0 => repeat([1], 5))
Такую матрицу тоже можно визуализировать без каких-либо проблем.
heatmap( eye_spdiagm, yflip=:true, c=:Greens )
Но, как мы убедимся, она занимает больше памяти, чем все предыдущие варианты.
varinfo( r"eye_array|eye_I|eye_Diagonal|eye_diagm|eye_spdiagm" )
Заключение¶
Мы сравнили несколько способов создания единичных матриц. Меньше всего в памяти занимает матрица, созданная с применением стандартного объекта I
.