Có bất kỳ lib C ++ (hoặc C) nào có mảng giống NumPy với hỗ trợ cho các phép toán cắt, vectơ hóa, thêm và trừ nội dung theo từng phần tử, v.v. không?
Có bất kỳ lib C ++ (hoặc C) nào có mảng giống NumPy với hỗ trợ cho các phép toán cắt, vectơ hóa, thêm và trừ nội dung theo từng phần tử, v.v. không?
Câu trả lời:
Dưới đây là một số phần mềm miễn phí có thể phù hợp với nhu cầu của bạn.
Các Thư viện khoa học GNU là một phần mềm GPL viết bằng C. Do đó, nó có một C-như phân bổ và cách lập trình (con trỏ, vv). Với GSLwrap , bạn có thể có cách lập trình C ++ trong khi vẫn sử dụng GSL. GSL có triển khai BLAS , nhưng bạn có thể sử dụng ATLAS thay vì CBLAS mặc định, nếu bạn muốn nhiều hiệu suất hơn nữa.
Các tăng / uBLAS thư viện là một thư viện BSL, viết bằng C ++ và phân phối như là một gói tăng. Nó là một C ++ - cách thực hiện tiêu chuẩn BLAS. uBLAS đi kèm với một vài hàm đại số tuyến tính và có một ràng buộc thực nghiệm với ATLAS .
eigen là một thư viện đại số tuyến tính được viết bằng C ++, được phân phối theo giấy phép MPL2 (bắt đầu từ phiên bản 3.1.1) hoặc LGPL3 / GPL2 (các phiên bản cũ hơn). Đó là một cách lập trình C ++, nhưng được tích hợp nhiều hơn hai cách khác (có sẵn nhiều thuật toán và cấu trúc dữ liệu hơn). Eigen tuyên bố là nhanh hơn các triển khai BLAS ở trên, trong khi không tuân theo API BLAS tiêu chuẩn de-facto. Eigen dường như không đặt nhiều nỗ lực vào việc thực hiện song song.
Armadillo là thư viện LGPL3 cho C ++. Nó có ràng buộc cho LAPACK (thư viện được sử dụng bởi numpy). Nó sử dụng các mẫu đệ quy và lập trình siêu mẫu, đó là một điểm tốt (tôi không biết liệu các thư viện khác có làm điều đó không?).
xtensor là một thư viện C ++ được cấp phép BSD. Nó cung cấp một API C ++ rất giống với API của NumPy. Xem https://xtensor.readthedocs.io/en/latest/numpy.html để biết bảng gian lận.
Những lựa chọn thay thế này thực sự tốt nếu bạn chỉ muốn lấy cấu trúc dữ liệu và đại số tuyến tính cơ bản. Tùy thuộc vào sở thích của bạn về kiểu dáng, giấy phép hoặc thách thức sysadmin (cài đặt các thư viện lớn như LAPACK có thể khó khăn), bạn có thể chọn cái phù hợp nhất với nhu cầu của mình.
a[:4,::-1,:,19] = b[None,-5:,None]
hoặc a[a>5]=0
tương tự, cũng như có sẵn một bộ khổng lồ các hàm thao tác chỉ mục và mảng. Tôi thực sự hy vọng một ngày nào đó ai đó tạo ra một cái gì đó như vậy cho C ++.
a.colRange(4,7).rowRange(4,8)
cho a[4:7,4,8]
) và mặt nạ điều kiện ( a.setTo(cv::Scalar(0), a>5)
cho a[a>5]=0
)
Hãy thử xtensor . (Xem NumPy to Xtensor Cheat Sheet ).
xtensor là một thư viện C ++ dùng để phân tích số với các biểu thức mảng đa chiều.
xtensor cung cấp
Thí dụ
Khởi tạo mảng 2-D và tính tổng của một trong các hàng của nó và mảng 1-D.
#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
xt::xarray<double> arr1
{{1.0, 2.0, 3.0},
{2.0, 5.0, 7.0},
{2.0, 5.0, 7.0}};
xt::xarray<double> arr2
{5.0, 6.0, 7.0};
xt::xarray<double> res = xt::view(arr1, 1) + arr2;
std::cout << res;
Kết quả đầu ra
{7, 11, 14}
Khởi tạo mảng 1-D và định hình lại nó ở vị trí.
#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
xt::xarray<int> arr
{1, 2, 3, 4, 5, 6, 7, 8, 9};
arr.reshape({3, 3});
std::cout << arr;
Kết quả đầu ra
{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}}
DyND được thiết kế để trở thành một thư viện giống NumPy cho C ++. Những thứ như phát sóng, toán tử số học và cắt đều hoạt động tốt. Mặt khác, nó vẫn rất thử nghiệm và nhiều tính năng vẫn chưa được triển khai.
Đây là cách triển khai đơn giản của thuật toán de Casteljau trong C ++ bằng cách sử dụng mảng DyND:
#include <iostream>
#include <dynd/array.hpp>
using namespace dynd;
nd::array decasteljau(nd::array a, double t){
size_t e = a.get_dim_size();
for(size_t i=0; i < e-1; i++){
a = (1.-t) * a(irange()<(e-i-1)) + t * a(0<irange());
}
return a;
}
int main(){
nd::array a = {1., 2., 2., -1.};
std::cout << decasteljau(a, .25) << std::endl;
}
Tôi đã viết một bài đăng trên blog cách đây ít lâu với nhiều ví dụ hơn và so sánh song song về cú pháp cho Fortran 90, DyND trong C ++ và NumPy trong Python.
Tuyên bố từ chối trách nhiệm: Tôi là một trong những nhà phát triển DyND hiện tại.
Eigen là một thư viện đại số tuyến tính tốt.
http://eigen.tuxfamily.org/index.php?title=Main_Page
Nó khá dễ cài đặt vì nó là một thư viện chỉ dành cho tiêu đề. Nó dựa vào mẫu để tạo mã được tối ưu hóa tốt. Nó vectơ hóa tự động các hoạt động của ma trận.
Nó cũng hỗ trợ đầy đủ các phép toán khôn ngoan theo hệ số, chẳng hạn như "phép nhân mỗi phần tử" giữa hai ma trận. Nó là những gì bạn cần?
Blitz ++ hỗ trợ mảng với số lượng trục tùy ý, trong khi Armadillo chỉ hỗ trợ tối đa ba (vectơ, ma trận và hình khối). Eigen chỉ hỗ trợ vectơ và ma trận (không phải hình khối). Nhược điểm là Blitz ++ không có các hàm đại số tuyến tính ngoài các phép toán cơ bản và các phép co tensor. Sự phát triển dường như đã chậm lại một thời gian trước đây, nhưng có lẽ đó chỉ là vì thư viện làm những gì nó làm và không có nhiều thay đổi cần được thực hiện.
xtensor là tốt, nhưng cuối cùng tôi đã tự viết một thư viện nhỏ như một dự án đồ chơi với c ++ 20, trong khi cố gắng giữ giao diện đơn giản nhất có thể. Đây rồi: https://github.com/gbalduzz/NDArray
Mã ví dụ:
using namespace nd;
NDArray<int, 2> m(3, 3); // 3x3 matrix
m = 2; // assign 2 to all
m(-1, all) = 1; // assign 1 to the last row.
auto tile = m(range{1, end}, range{1, end}); // 2x2 tile
std::sort(tile.begin(), tile.end());
std::cout << m; // prints [[2, 2, 2], [2, 1, 1], [1, 2, 2]]
Nó không cung cấp các toán tử số học ưa thích thu gọn nhiều phép toán lại với nhau, nhưng bạn có thể phát các lambdas tùy ý đến một tập hợp các tensor có cùng hình dạng hoặc sử dụng các toán tử số học được đánh giá một cách lười biếng.
Hãy cho tôi biết bạn nghĩ gì về giao diện và cách nó so sánh với các tùy chọn khác, và nếu điều này có bất kỳ hy vọng nào, bạn muốn thực hiện loại thao tác nào.
Giấy phép miễn phí và không phụ thuộc!
Phụ lục: Tôi đã quản lý để biên dịch và chạy xtensor đúng cách, và kết quả là thư viện của tôi nhanh hơn đáng kể khi lặp qua các chế độ xem (2 đến 3X)
VIGRA chứa một triển khai mảng N chiều tốt:
http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html
Tôi sử dụng rộng rãi, và thấy nó rất đơn giản và hiệu quả. Nó cũng chỉ có tiêu đề, vì vậy rất dễ dàng để tích hợp vào môi trường phát triển của bạn. Đó là điều gần nhất mà tôi đã gặp khi sử dụng NumPy về API của nó.
Nhược điểm chính là nó không được sử dụng rộng rãi như những cái khác, vì vậy bạn sẽ không tìm thấy nhiều trợ giúp trực tuyến. Điều đó và nó được đặt tên một cách khó hiểu (hãy thử tìm kiếm nó!)
Sử dụng LibTorch (giao diện người dùng PyTorch cho C ++) và vui vẻ.
Đây là một câu hỏi cũ. Vẫn cảm thấy muốn trả lời. Suy nghĩ có thể giúp ích cho nhiều người, Đặc biệt là mã hóa pydevs trong C ++.
Nếu bạn đã làm việc với python numpy, thì NumCpp là một lựa chọn tuyệt vời. Nó tối giản về cú pháp và có các hàm hoặc phương thức tương tự như py numpy.
Phần so sánh trong doc readme cũng rất hay.
NumCpp
nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();
Nếu bạn muốn sử dụng mảng đa chiều (như numpy) để xử lý hình ảnh hoặc mạng nơ-ron, bạn có thể sử dụng OpenCV
cv::Mat
cùng với rất nhiều thuật toán xử lý hình ảnh. Trong trường hợp bạn CHỈ muốn sử dụng nó cho các hoạt động ma trận, bạn chỉ cần biên dịch các mô-đun opencv tương ứng để giảm kích thước và có thư viện OpenCV nhỏ.
cv::Mat
(Ma trận) là một mảng n chiều có thể được sử dụng để lưu trữ nhiều loại dữ liệu khác nhau, chẳng hạn như RGB, HSV hoặc hình ảnh thang độ xám, vectơ có giá trị thực hoặc phức, các ma trận khác, v.v.
A Mat chứa các thông tin sau: width, height, type, channels, data, flags, datastart, dataend
và như vậy.
Nó có một số phương pháp để thao tác với ma trận. Phần thưởng bạn cũng có thể tạo trên các lõi CUDA cv::cuda::GpuMat
.
Hãy xem xét tôi muốn tạo một ma trận với 10 hàng, 20 cột, nhập CV_32FC3:
int R = 10, C = 20;
Mat m1;
m1.create(R, C, CV_32FC3); //creates empty matrix
Mat m2(cv::Size(R, C), CV_32FC3); // creates a matrix with R rows, C columns with data type T where R and C are integers,
Mat m3(R, C, CV_32FC3); // same as m2
TẶNG KEM:
Biên dịch thư viện opencv nhỏ và nhỏ gọn chỉ cho các phép toán ma trận. Một khi các cách như được đề cập trong bài viết này.
HOẶC LÀ
biên dịch mã nguồn opencv bằng lệnh cmake sau:
$ git clone https://github.com/opencv/opencv.git
$ cd opencv
$ git checkout <version you want to checkout>
$ mkdir build
$ cd build
$ cmake -D WITH_CUDA=OFF -D WITH_MATLAB=OFF -D BUILD_ANDROID_EXAMPLES=OFF -D BUILD_DOCS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF -DANDROID_STL=c++_shared -DBUILD_SHARED_LIBS=ON -D BUILD_opencv_objdetect=OFF -D BUILD_opencv_video=OFF -D BUILD_opencv_videoio=OFF -D BUILD_opencv_features2d=OFF -D BUILD_opencv_flann=OFF -D BUILD_opencv_highgui=OFF -D BUILD_opencv_ml=OFF -D BUILD_opencv_photo=OFF -D BUILD_opencv_python=OFF -D BUILD_opencv_shape=OFF -D BUILD_opencv_stitching=OFF -D BUILD_opencv_superres=OFF -D BUILD_opencv_ts=OFF -D BUILD_opencv_videostab=OFF -D BUILD_opencv_dnn=OFF -D BUILD_opencv_imgproc=OFF ..
$ make -j $nproc
$ sudo make install
Hãy thử ví dụ này:
#include "opencv2/core.hpp"
#include<iostream>
int main()
{
std::cout << "OpenCV Version " << CV_VERSION << std::endl;
int R = 2, C = 4;
cv::Mat m1;
m1.create(R, C, CV_32FC1); //creates empty matrix
std::cout << "My Mat : \n" << m1 << std::endl;
}
Biên dịch mã bằng lệnh sau:
$ g++ -std=c++11 opencv_mat.cc -o opencv_mat `pkg-config --libs opencv` `pkg-config --cflags opencv`
Chạy tệp thực thi:
$ ./opencv_mat
OpenCV Version 3.4.2
My Mat :
[0, 0, 0, 0;
0, 0, 0, 0]
Các GSL là rất tốt, nó làm tất cả những gì bạn đang yêu cầu và nhiều hơn nữa. Nó được cấp phép theo GPL.
Trong khi GLM được thiết kế để kết hợp dễ dàng với OpenGL và GLSL, nó là một thư viện toán học chỉ tiêu đề đầy đủ chức năng cho C ++ với một bộ giao diện rất trực quan.
Nó khai báo các kiểu vector & ma trận cũng như các phép toán khác nhau trên chúng.
Nhân hai ma trận đơn giản là (M1 * M2). Trừ hai vectơ (V1- V2).
Việc truy cập các giá trị chứa trong vectơ hoặc ma trận cũng đơn giản như nhau. Sau khi khai báo một vec-tơ vec3 chẳng hạn, người ta có thể truy cập phần tử đầu tiên của nó với vec-tơ.x. Kiểm tra nó ra.