Привет, Хабр!
Линейная алгебра сейчас применяется практические везде. В связс с этим сегодня рассмотрим одну из библиотек для Rust — nalgebra.
Основная цель nalgebra — предоставить инструмент для работы с линейной алгеброй.
Основные возможности
Векторы
Векторы в nalgebra могут быть как статически, так и динамически выделяемыми. Векторы со статическими размерами известны на этапе компиляции и хранятся в стеке, тогда как динамические векторы выделяются в куче.
Пример статического вектора:
use nalgebra::Vector3; fn main() { let v = Vector3::new(1.0, 2.0, 3.0); println!("Vector: {:?}", v); }
Пример динамического вектора:
use nalgebra::DVector; fn main() { let v = DVector::from_vec(vec![1.0, 2.0, 3.0, 4.0]); println!("Dynamic Vector: {:?}", v); }
Матрицы
Матрицы также могут быть статическими и динамическими. Статические матрицы имеют размеры, известные на этапе компиляции, тогда как размеры динамических матриц могут изменяться во время выполнения.
Пример статической матрицы:
use nalgebra::Matrix3; fn main() { let m = Matrix3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); println!("Matrix:\n{}", m); }
Пример динамической матрицы:
use nalgebra::DMatrix; fn main() { let m = DMatrix::from_row_slice(3, 3, &[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 ]); println!("Dynamic Matrix:\n{}", m); }
Операции с векторами и матрицами включают сложение, умножение, транспонирование, инверсию и другие стандартные линейные операции.
Точки и трансформации
Точки
Точки в nalgebra представляют собой координаты в пространстве. Их используют для обозначения положений объектов, в отличие от векторов, которые обозначают направления и расстояния.
Пример:
use nalgebra::{Point2, Point3}; fn main() { let p2 = Point2::new(1.0, 2.0); let p3 = Point3::new(1.0, 2.0, 3.0); println!("Point2: {:?}", p2); println!("Point3: {:?}", p3); }
Трансформации
Трансформации включают в себя различные операции, такие как переводы, вращения и масштабирования.
Пример:
use nalgebra::{Translation3, Rotation3, Isometry3, Vector3}; fn main() { let translation = Translation3::new(1.0, 2.0, 3.0); let rotation = Rotation3::from_axis_angle(&Vector3::z_axis(), 0.785398163); // 45 degrees in radians let isometry = Isometry3::new(translation.vector, rotation.scaled_axis()); println!("Isometry:\n{}", isometry); }
Специфические структуры данных
Кватернионы
Кватернионы используются для представления и вычисления 3D вращений. Иногда это некий мастхев для анимаций и графических приложений из-за своей компактности и отсутствия эффекта «гимбаллок«.
Пример:
use nalgebra::{Quaternion, UnitQuaternion}; fn main() { let axis = Vector3::y_axis(); let angle = 1.57; // 90 degrees in radians let quaternion = UnitQuaternion::from_axis_angle(&axis, angle); println!("Quaternion: {:?}", quaternion); }
Изометрии
Изометрия сочетает в себе перевод и вращение. Эта структура нужна для представления позиций и ориентаций объектов в пространстве.
Пример:
use nalgebra::{Isometry3, Vector3}; fn main() { let translation = Vector3::new(1.0, 2.0, 3.0); let rotation = Vector3::new(0.0, 1.0, 0.0); // Rotate around Y axis let iso = Isometry3::new(translation, rotation); println!("Isometry:\n{}", iso); }
Гомогенные матрицы
Гомогенные матрицы используются для представления общих линейных преобразований: переводы, вращения, масштабирования и сдвиги.
Пример:
use nalgebra::Matrix4; fn main() { let mut m = Matrix4::identity(); m[(0, 3)] = 1.0; // Translation along X axis m[(1, 1)] = 0.5; // Scaling along Y axis println!("Homogeneous Matrix:\n{}", m); }
Прочие возможности
Факторизации матриц
Факторизация матриц — это процесс разложения матрицы на произведение нескольких матриц, что очень часто используют для решения систем линейных уравнений, вычисления обратных матриц и определителей.
LU-разложение
LU-разложение разделяет матрицу на нижнюю треугольную матрицу и верхнюю треугольную матрицу
.
Пример кода:
use nalgebra::DMatrix; fn main() { let matrix = DMatrix::from_row_slice(3, 3, &[2.0, 1.0, 1.0, 4.0, -6.0, 0.0, -2.0, 7.0, 2.0]); let lu = matrix.lu(); let l = lu.l(); let u = lu.u(); println!("L:\n{}", l); println!("U:\n{}", u); }
QR-разложение
QR-разложение разлагает матрицу на ортогональную матрицу и верхнюю треугольную матрицу
.
Пример кода:
use nalgebra::DMatrix; fn main() { let matrix = DMatrix::from_row_slice(3, 3, &[12.0, -51.0, 4.0, 6.0, 167.0, -68.0, -4.0, 24.0, -41.0]); let qr = matrix.qr(); let q = qr.q(); let r = qr.r(); println!("Q:\n{}", q); println!("R:\n{}", r); }
SVD-разложение
SVD-разложение представляет матрицу в виде произведения трех матриц: ,
диагональная матрица с сингулярными значениями и
.
Пример разложения:
use nalgebra::DMatrix; fn main() { let matrix = DMatrix::from_row_slice(3, 2, &[1.0, 0.0, 0.0, 1.0, 1.0, 1.0]); let svd = matrix.svd(true, true); let u = svd.u.unwrap(); let s = svd.singular_values; let v_t = svd.v_t.unwrap(); println!("U:\n{}", u); println!("Σ:\n{}", s); println!("V^T:\n{}", v_t); }
Специальные виды матриц
Разреженные матрицы
Разреженные матрицы содержат преимущественно нулевые элементы, что частенько позволяет сэкономить память. В nalgebra поддерживаются различные форматы разреженных матриц, такие как compressed sparse column и compressed sparse row.
Пример создания разреженной матрицы:
use nalgebra_sparse::csr::CsrMatrix; fn main() { let num_rows = 4; let num_cols = 4; let row_offsets = vec![0, 2, 4, 7, 8]; let col_indices = vec![0, 1, 1, 2, 0, 2, 3, 3]; let values = vec![10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]; let csr = CsrMatrix::try_from_csr_data(num_rows, num_cols, row_offsets, col_indices, values).unwrap(); println!("CSR Matrix:\n{}", csr); }
Ортографические и перспективные проекции
Ортографические и перспективные проекции используют в компьютерной графике для отображения трехмерных сцен на двумерный экран.
Пример ортографической проекции:
use nalgebra::Orthographic3; fn main() { let orthographic = Orthographic3::new(-1.0, 1.0, -1.0, 1.0, 0.1, 100.0); println!("Orthographic Projection:\n{}", orthographic.as_matrix()); }
Пример перспективной проекции:
use nalgebra::Perspective3; fn main() { let perspective = Perspective3::new(16.0 / 9.0, 3.14 / 4.0, 0.1, 100.0); println!("Perspective Projection:\n{}", perspective.as_matrix()); }
Вычисления на GPU и встраиваемые системы
Nalgebra поддерживает компиляцию для WebAssembly и различные встраиваемые системы.
Пример компиляции для WebAssembly:
# В Cargo.toml добавьте поддержку wasm [dependencies] nalgebra = "0.27" wasm-bindgen = "0.2" # В main.rs use nalgebra::Vector3; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn add_vectors(a: &Vector3<f32>, b: &Vector3<f32>) -> Vector3<f32> { a + b }
Для компиляции есть команда:
wasm-pack build --target web
Nalgebra также может использоваться с библиотеками для GPU вычислений, такими как wgpu и ash.
Библиотека nalgebra — мощный и гибкий инструмент для работы с линейной алгеброй в Rust.
Что делать, если у вас неопытная команда, а надо делать сложную задачу? Можно написать заявление об увольнении, а потом с ужасом рассказывать в интернете про прошлые места работы. А можно попробовать выстроить процессы так, чтобы получить требуемый результат. На открытом уроке мы не будем обсуждать, какая из этих двух стратегий правильная, но поговорим о том, как математика может помочь выстроить архитектуру приложения, которая позволит решить эту трудную задачу.
Урок пройдёт в рамках курса «Математика для программистов» 26 июля. Записаться можно по ссылке.
ссылка на оригинал статьи https://habr.com/ru/articles/828316/
Добавить комментарий