Tablice w stylu NumPy dla C ++? [Zamknięte]

84

Czy są jakieś biblioteki C ++ (lub C), które mają tablice podobne do NumPy z obsługą wycinania, operacji wektoryzacji, dodawania i odejmowania zawartości element po elemencie itp.?

Llamageddon
źródło
2
Armadillo ?
Oliver Charlesworth
1
O ile wiem, numpy używa LAPACK . Chociaż jest to napisane w języku Fortran, dostępne są wiązania C ++. Nigdy jednak nie użyłem żadnego z nich.
Voo
Istnieje nowy interfejs C ++ programu NumPy o nazwie ArmaNpy .
mtall
1
Nie widzę Boost.MultiArray w komentarzach jeszcze
Dmitry Ledentsov
Możesz spróbować osadzić Pythona i faktycznie użyć numpy, co miałoby tę zaletę, że nie musiałoby się uczyć nowej biblioteki, chociaż byłoby to wolniejsze niż użycie biblioteki C / C ++.
Kevin

Odpowiedzi:

61

Oto kilka bezpłatnych programów, które mogą odpowiadać Twoim potrzebom.

  1. GNU Scientific Library to oprogramowanie GPL napisany w C. Tak więc, ma C-jak przydzielania i sposobu programowania (wskaźniki, etc.). Dzięki GSLwrap możesz programować w języku C ++, nadal używając GSL. GSL ma implementację BLAS , ale możesz użyć ATLAS zamiast domyślnego CBLAS, jeśli chcesz uzyskać jeszcze więcej wydajności.

  2. Biblioteka boost / uBLAS jest biblioteką BSL napisaną w C ++ i rozpowszechnianą jako pakiet boost. Jest to sposób implementacji standardu BLAS w C ++. uBLAS zawiera kilka funkcji algebry liniowej oraz istnieje eksperymentalne powiązanie z ATLAS .

  3. eigen to biblioteka algebry liniowej napisana w C ++, rozpowszechniana na licencji MPL2 (począwszy od wersji 3.1.1) lub LGPL3 / GPL2 (starsze wersje). Jest to sposób programowania w C ++, ale bardziej zintegrowany niż dwa pozostałe (dostępnych jest więcej algorytmów i struktur danych). Eigen twierdzi, że jest szybszy niż powyższe implementacje BLAS, ale nie jest zgodny z de facto standardowym BLAS API. Wydaje się, że Eigen nie wkłada wiele wysiłku w równoległe wdrażanie.

  4. Armadillo to biblioteka LGPL3 dla C ++. Posiada powiązanie z LAPACK (biblioteka używana przez numpy). Używa szablonów rekurencyjnych i metaprogramowania szablonów, co jest dobrym punktem (nie wiem, czy inne biblioteki też to robią?).

  5. xtensor to biblioteka C ++ na licencji BSD. Oferuje API C ++ bardzo podobne do NumPy. Zobacz https://xtensor.readthedocs.io/en/latest/numpy.html, aby uzyskać ściągawkę.

Te alternatywy są naprawdę dobre, jeśli chcesz tylko uzyskać struktury danych i podstawową algebrę liniową. W zależności od gustu w kwestii stylu, licencji lub wyzwań administratora systemu (instalacja dużych bibliotek, takich jak LAPACK może być trudna), możesz wybrać tę, która najlepiej odpowiada Twoim potrzebom.

nojhan
źródło
16
Wierz lub nie, ale moja odpowiedź jest wynikiem moich własnych poszukiwań sprzed miesiąca. Wierzyłem, że zebranie informacji, które pomogły mi w dokonaniu wyboru, będzie interesujące. Nie jestem pewien, czy lepiej jest mieć kilka informacji rozłożonych na odpowiedzi. Nadal możesz głosować za wszystkich, jeśli bardziej zależy Ci na etyce niż na wydajności.
nojhan
19
Niestety, żadna z nich nie zapewnia niczego tak ogólnego i wygodnego, jak tablice numpy. Tablice Numpy są dowolnie wymiarowe i obsługują takie rzeczy jak a[:4,::-1,:,19] = b[None,-5:,None]lub a[a>5]=0i podobne, a także mają ogromny zestaw dostępnych funkcji manipulowania tablicami i indeksami. Naprawdę mam nadzieję, że ktoś kiedyś zrobi coś takiego dla C ++.
amaurea
2
OpenCV ma również typ Matrix, który może mieć dowolny rozmiar wymiarowy; zakresy kolumn / wierszy ( a.colRange(4,7).rowRange(4,8)for a[4:7,4,8]) i maska ​​warunków ( a.setTo(cv::Scalar(0), a>5)for a[a>5]=0)
xaedes
3
@amaurea sprawdź odpowiedź na xtensor poniżej, który umożliwia wszystkie powyższe.
Quant
1
Musiałem użyć Eigena w ostatnim projekcie i muszę powiedzieć, że chociaż wydaje się być skuteczny, składnia jest absolutnie okropna. Nie ma takiej niesamowitej składni cięcia Pythona. Na przykład, jeśli masz wektor 1D x i chcesz manipulować pierwszymi n elementami, musisz użyć x.head (n). Nie pytaj nawet o manipulowanie dowolnym wycinkiem x, będziesz potrzebować do tego dobrej starej pętli for. To tylko jeden z wielu niezgrabnych i niewygodnych przykładów, które mógłbym wymienić.
Alex
54

Wypróbuj xtensor . (Zobacz ściągawkę NumPy to Xtensor ).

xtensor to biblioteka C ++ przeznaczona do analizy numerycznej z wielowymiarowymi wyrażeniami tablicowymi.

xtensor zapewnia

  • rozszerzalny system ekspresji umożliwiający nadawanie w stylu numpy.
  • API zgodne z idiomami biblioteki standardowej C ++.
  • narzędzia do manipulowania wyrażeniami tablicowymi i budowania w oparciu o xtensor.

Przykład

Zainicjuj tablicę 2-w i oblicz sumę jednego z jej wierszy i tablicy 1-w.

#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;

Wyjścia

{7, 11, 14}

Zainicjuj tablicę 1-W i zmień jej kształt w miejscu.

#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;

Wyjścia

{{1, 2, 3},
 {4, 5, 6},
 {7, 8, 9}}
Quant
źródło
2
@Llamageddon Czy uważasz, że to powinna być wybrana odpowiedź?
Quant,
7

DyND został zaprojektowany między innymi jako biblioteka podobna do NumPy dla C ++. Takie rzeczy jak nadawanie, operatory arytmetyczne i wycinanie działają dobrze. Z drugiej strony nadal jest bardzo eksperymentalny i wiele funkcji nie zostało jeszcze zaimplementowanych.

Oto prosta implementacja algorytmu de Casteljau w C ++ przy użyciu tablic 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;
}

Niedawno napisałem post na blogu z większą ilością przykładów i porównaniami składni dla Fortran 90, DyND w C ++ i NumPy w Pythonie.

Zastrzeżenie: jestem jednym z obecnych programistów DyND.

IanH
źródło
3

Eigen to dobra biblioteka algebry liniowej.

http://eigen.tuxfamily.org/index.php?title=Main_Page

Jest dość łatwa do zainstalowania, ponieważ jest to biblioteka zawierająca tylko nagłówki. Opiera się na szablonie, aby wygenerować dobrze zoptymalizowany kod. Wektoryzuje automatycznie operacje macierzowe.

Obsługuje również w pełni operacje oparte na współczynnikach, takie jak na przykład mnożenie na element między dwiema macierzami. To jest to, czego potrzebujesz?

Frédéric Terrazzoni
źródło
3
Jednak składnia Eigena jest dość okropna. Nie ma takiej płynnej składni krojenia, którą można znaleźć w Numpy. I nie jest to ogólna n-wymiarowa biblioteka tablic, jest bardziej przeznaczona tylko dla wektorów 1D i macierzy 2D. Fakt, że mają VectorXd dla tablic 1D i MatrixXd dla tablic 2D już mnie odpycha.
Alex
2

Blitz ++ obsługuje tablice z dowolną liczbą osi, podczas gdy Armadillo obsługuje tylko do trzech (wektory, macierze i kostki). Eigen obsługuje tylko wektory i macierze (nie kostki). Wadą jest to, że Blitz ++ nie ma funkcji algebry liniowej poza podstawowymi operacjami entrywise i skróceniami tensorowymi. Wydaje się, że rozwój zwolnił już jakiś czas temu, ale może to tylko dlatego, że biblioteka robi to, co robi i nie trzeba wprowadzać wielu zmian.

Dan Stahlke
źródło
2

xtensor jest dobry, ale ostatecznie napisałem mini-bibliotekę jako projekt zabawki w języku c ++ 20, starając się jednocześnie maksymalnie uprościć interfejs. Oto on: https://github.com/gbalduzz/NDArray

Przykładowy kod:

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]]

Nie zapewnia jeszcze wymyślnych operatorów arytmetycznych, które zwijają wiele operacji razem, ale można rozgłaszać dowolne lambdy do zestawu tensorów o tym samym kształcie lub używać leniwie ocenianych operatorów arytmetycznych.

Daj mi znać, co myślisz o interfejsie i jak wypada on w porównaniu z innymi opcjami, a jeśli ma to jakąkolwiek nadzieję, jakie operacje chciałbyś zobaczyć zaimplementowane.

Darmowa licencja i brak zależności!

Dodatek: Udało mi się poprawnie skompilować i uruchomić xtensor, w wyniku czego moja biblioteka jest znacznie szybsza podczas iteracji po widokach (2 do 3X)

Giovanni Balduzzi
źródło
1

VIGRA zawiera dobrą implementację tablicy N-wymiarowej:

http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html

Używam go intensywnie i uważam, że jest bardzo prosty i skuteczny. Jest to również tylko nagłówek, dzięki czemu jest bardzo łatwy do zintegrowania ze środowiskiem programistycznym. Jest to najbliższa rzecz, z jaką się spotkałem przy korzystaniu z NumPy, jeśli chodzi o jego API.

Głównym minusem jest to, że nie jest tak szeroko stosowany jak inne, więc nie znajdziesz zbyt wiele pomocy w Internecie. To i ma niezręczną nazwę (spróbuj go wyszukać!)

Jaskółka oknówka
źródło
1

Użyj LibTorch (nakładka PyTorch dla C ++) i bądź szczęśliwy.

Артем Ященко
źródło
1

To jest stare pytanie. Nadal miałam ochotę odpowiedzieć. Myśl może pomóc wielu, zwłaszcza pidevs kodowanie w C ++.

Jeśli już pracowałeś z Pythonem numpy, NumCpp to świetny wybór. Jest minimalistyczny w składni i ma podobne funkcje lub metody jak py numpy.

Część porównawcza w dokumencie readme jest również bardzo fajna.

NumCpp

nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();
Sayan Dey
źródło
0

Eigen to biblioteka szablonów dla algebry liniowej (macierze, wektory…). Jest dostępny tylko w nagłówku i darmowy (LGPL).

Claudio
źródło
0

Jeśli chcesz używać wielowymiarowej tablicy (takiej jak numpy) do przetwarzania obrazu lub sieci neuronowej, możesz użyć OpenCV cv::Matwraz z mnóstwem algorytmów przetwarzania obrazu. Jeśli chcesz go używać TYLKO do operacji na macierzach, wystarczy skompilować odpowiednie moduły opencv, aby zmniejszyć rozmiar i mieć małą bibliotekę OpenCV.

cv::Mat(Matryca) to n-wymiarowa tablica, która może być używana do przechowywania różnego rodzaju danych, takich jak obrazy RGB, HSV lub w skali szarości, wektory z wartościami rzeczywistymi lub złożonymi, inne macierze itp.

Mata zawiera następujące informacje: width, height, type, channels, data, flags, datastart, dataendi tak dalej.

Posiada kilka metod manipulacji macierzą. Bonus, który możesz następnie stworzyć na rdzeniach CUDA, a także cv::cuda::GpuMat.

Rozważ, że chcę utworzyć macierz z 10 wierszami, 20 kolumnami, wpisz 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

PREMIA:

Skompiluj małą i kompaktową bibliotekę opencv do wykonywania tylko operacji na macierzach. Jeden ze sposobów jest taki, jak wspomniano w tym artykule.

LUB

skompiluj kod źródłowy opencv za pomocą następującego polecenia cmake:

$ 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

Wypróbuj ten przykład:

 #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;
 }

Skompiluj kod za pomocą następującego polecenia:

$ g++ -std=c++11 opencv_mat.cc -o opencv_mat `pkg-config --libs opencv` `pkg-config --cflags opencv`

Uruchom plik wykonywalny:

$ ./opencv_mat

OpenCV Version 3.4.2
My Mat :
[0, 0, 0, 0;
 0, 0, 0, 0]
Milind Deore
źródło
-1

GSL jest super, robi wszystko, co prosisz i wiele więcej. Jest jednak licencjonowany na licencji GPL.

Matt Phillips
źródło
-1

Chociaż GLM został zaprojektowany tak, aby łatwo łączyć się z OpenGL i GLSL, jest to w pełni funkcjonalna biblioteka matematyczna dla C ++ tylko z nagłówkiem z bardzo intuicyjnym zestawem interfejsów.

Deklaruje typy wektorowe i macierzowe, a także różne operacje na nich.

Mnożenie dwóch macierzy jest proste jak (M1 * M2). Odejmowanie dwóch wektorów (V1-V2).

Dostęp do wartości zawartych w wektorach lub macierzach jest równie prosty. Na przykład po zadeklarowaniu wektora vec3 można uzyskać dostęp do jego pierwszego elementu za pomocą vector.x. Sprawdź to.


źródło