2014-11-03 14 views
5

Ich versuche gerade, etwas Python-Code in C++ zu konvertieren. Ein "kleines" Problem ist die Änderung der Dimensionen einer Matrix. Ist es möglich, eine Matrix in C++ ähnlich der Python reshape Funktion umzuformen?Wie man eine Matrix umformt?

Zum Beispiel, in Python kann ich einfach ein Array mit numpy erstellen und die Abmessungen leicht umformen.

a = np.array([[1,2,3],[4,5,6]]) 
>>> a.reshape(3,2) 
array([[1, 2], 
     [3, 4], 
     [5, 6]]) 

Wie könnte ich das in C++ tun? Vielleicht ist das eine einfache Frage, aber ich bin dazu völlig unfähig. Ich habe dies innerhalb der OpenCV-Bibliothek mit der Mat Klasse here gesehen, aber es erweist sich als wahnsinnig schwierig, richtig mit MinGW zu arbeiten, ganz zu schweigen von einer sehr großen Addition für eine einzelne Funktion. Es wäre ideal, wenn dies mit Basisfunktionen möglich wäre.

+0

Das ist eigentlich eine sehr knifflige Frage. In NumPy ist es einfach, weil NumPy-Arrays tatsächlich ihre Schritte und ihre Form verfolgen; [Dieser Artikel] (http://arxiv.org/pdf/1102.1523) beschreibt die Struktur und kann selbst für C++ - Programme Inspiration liefern. –

Antwort

4

Soweit die Erinnerung aneinander angrenzend verlegt wird (zB Ebene C-Arrays), können Sie den Typen mit unterschiedlichen Indizes neu interpretieren können:

int array[2][3] = { { 1, 2, 3 }, 
         { 4, 5, 6 } 
        }; 

// Reinterpret the array with different indices 
int(*array_pointer)[3][2] = reinterpret_cast<int(*)[3][2]>(array); 

for (int x = 0; x < 3; ++x) { 
    for (int y = 0; y < 2; ++y) 
     std::cout << (*array_pointer)[x][y] << " "; 
    std::cout << std::endl; 
} 
// Output: 
// 1 2 
// 3 4 
// 5 6 

Example

Die oben ist nur ein Beispiel zu zeigen, dass das Problem wirklich kocht, wie Speicher in Ihrer Matrix-Klasse ausgelegt ist.

Falls Ihre Klasse intern std::vector<int> mit linearen Indizes verwendet, ist es ausreichend, diese Indizes neu zu interpretieren, um sie an Ihre Zugriffsmuster anzupassen.

+1

Genau das habe ich gesucht. Vielen Dank! – cdeterman

0

Es hängt von der Matrixklasse ab, die Sie verwenden. Wenn Sie schreiben Ihre eigene: Es gibt zwei gemeinsame Implementierungstechniken: ein std::vector<double>, mit Indexberechnungen der flachen Index zu finden, und ein std::vector<std::vector<double>>, mit einer Klasse invariant, dass alle Mitglieder des äußeren Vektor der haben muss gleiche Größe. Wenn Sie die erste verwenden, ist das Umformen einfach, solange wie die Gesamtgröße nicht ändert (und es ist schwer vorstellbar, was es sonst bedeuten würde). Wenn Sie die zweite verwenden, würde das Umformen wahrscheinlich erfordern, eine Kopie mit neuer Form zu konstruieren.

0

Es gibt keine Standard-Matrix-Bibliothek in C++, so dass Sie bei Matrizen auf sich allein gestellt sind. Eine Möglichkeit zum Speichern von Matrixdaten besteht in einer einfachen Anordnung. Sie müssen dann beim Zugriff auf einzelne Zeilen und Spalten eigene Zeilen- und Spaltenarithmetik durchführen. In Ihrem Fall wird die Umformung dann kostenlos, indem Sie einfach die Zeilen- und Spaltengrößen vertauschen.

Wenn Sie eine Matrixbibliothek möchten, versuchen Sie: GLM.

3

Hier ist ein Beispiel unter Verwendung von boost::ublas:

#include <iostream> 
#include <boost/numeric/ublas/matrix.hpp> 

//... 

using namespace boost::numeric::ublas; 

matrix<double> a(2, 3); 
a(0, 0) = 1; 
a(0, 1) = 2; 
a(0, 2) = 3; 
a(1, 0) = 4; 
a(1, 1) = 5; 
a(1, 2) = 6; 
matrix<double> r(3, 2, a.data()); 

for (int i = 0;i < 3;++i) 
{ 
    for (int j = 0;j < 2;++j) 
    std::cout << r(i, j) << ", "; 
    std::cout << std::endl; 
} 

1, 2,

3, 4,

5, 6,

1

Sehr leicht, einfach -zu verwenden C++ lineare Algebra-Bibliothek ist Armadillo, und es bietet reshape Funktionalität.

#include <armadillo> 
using namespace arma; 
int main() 
{ 
    // C++11 
    // mat a = { { 1, 2, 3 }, 
    // { 4, 5, 6 } }; 

    // C++98 
    mat a; 
    a << 1 << 2 << 3 << endr 
     << 2 << 4 << 6 << endr; 

    a.reshape(3, 2); 
    a.print(); 

    return 0; 
} 

Hinweis: Ich würde vorschlagen, nicht using namespace arma; zu tun und stattdessen tun arma::mat und arma::endr usw. ich es im Beispiel habe gerade für Klarheit.

Verwandte Themen