2012-06-11 17 views
14

Ich würde gerne die Eigen-Matrix-Bibliothek als lineare Algebra-Engine in meinem Programm verwenden. Eigen verwendet Expressionsvorlagen, um eine verzögerte Auswertung zu implementieren und Schleifen und Berechnungen zu vereinfachen.Wie integriert man eine Bibliothek, die Expression-Templates verwendet?

Zum Beispiel:

#include<Eigen/Core> 

int main() 
{ 
    int size = 40; 
    // VectorXf is a vector of floats, with dynamic size. 
    Eigen::VectorXf u(size), v(size), w(size), z(size); 
    u = 2*v + w + 0.2*z; 
} 

Da Eigen Expressionsschablonen verwendet, Code wie

u = 2*v + w + 0.2*z; 

In der oben erwähnten Probe auf eine einzige Schleife der Länge reduziert 10 (nicht 40, ist der Schwimmer setzen durch 4) in Register eintragen, ohne ein temporäres zu erzeugen. Wie cool ist das?

Aber wenn ich integrieren, um die Bibliothek wie folgt aus:

class UsingEigen 
{ 
    public: 
     UsingEigen(const Eigen::VectorXf& data): 
      data_(data) 
     {} 

     UsingEigen operator + (const UsingEigen& adee)const 
     { 
      return UsingEigen(data_ + adee.data_); 
     } 

     ... 
    private: 
     Eigen::VectorXf data_; 
} 

Dann werden die Ausdrücke wie:

UsingEigen a, b, c, d; 
a = b + c + d; 

kann nicht die Vorteile der Art und Weise nehmen Eigen umgesetzt wird. Und das ist nicht das letzte davon. Es gibt viele andere Beispiele, in denen Expression-Templates in Eigen verwendet werden.

Die einfache Lösung wäre nicht die Betreiber selbst zu definieren, schreibt data_ öffentlich zu machen und nur Ausdrücke wie:

UsingEigen a, b, c, d; 
a.data_ = b.data_ + c.data_ + d.data_; 

Dies bricht Verkapselung, aber es, die Effizienz des Eigens bewahrt.

Andere Möglichkeit könnte sein, meine eigenen Operatoren zu erstellen, aber sie sollen Expression-Templates zurückgeben. Aber da ich ein Anfänger in C++ bin, weiß ich nicht, ob das der richtige Weg ist.

Es tut mir leid, wenn die Frage zu allgemeiner Natur ist. Ich bin ein Anfänger und habe niemanden zu fragen. Bis jetzt habe ich überall std::vector<float> benutzt, aber jetzt muss ich auch Matrizen verwenden. In meinem gesamten Projekt von std::vector<float> zu Eigen zu wechseln, ist ein großer Schritt und ich habe Angst, gleich zu Beginn einen falschen Anruf zu machen. Jeder Rat ist willkommen!

+1

Interessantes Problem. Die erste Sache ist jedoch: Warum wollen Sie die Eigenbibliotheksvektoren auf diese Weise kapseln? Welches Verhalten fügen deine Klassen hinzu? –

+0

Meine Klassen fügen den Eigenbibliotheksklassen selbst keine Funktionalität hinzu, sondern verwenden sie. Zum Beispiel speichert eine meiner Kernklassen zwei Vektoren. Eins als Eingabe für eine bestimmte mathematische Berechnung und das andere als Ausgabe. Diese Objekte müssen auf ähnliche Weise zusammenarbeiten, wie ich oben erwähnt habe. Wenn Sie zwei solche Objekte hinzufügen, sollten die Eingaben hinzugefügt werden. –

+1

Ich glaube nicht, dass dies möglich ist, ohne einen wesentlichen Teil des Expression-Template-Frameworks selbst zu reproduzieren. Zum Beispiel ist '(a + b) * c 'so etwas wie' ExprCwiseAdd * UsingEigen' (der Name ist erfunden, erinnere mich nicht mehr daran), und es muss irgendwo 'ExprCwiseAdd * UsingEigen' definiert sein , aber auch 'ExprCwiseAdd * ExprCWiseAdd' und so weiter. Kurz gesagt, der Zusatz wird nicht 'UsingEigen' als Rückgabetyp haben. (Sie können sich [boost :: proto] (http://www.boost.org/doc/libs/1_49_0/doc/html/proto.html) ansehen, welches ein Framework für Expression-Templates ist). Viel Glück. – eudoxos

Antwort

4

Warum würde data_ brechen Einkapselung? Kapselung bedeutet, dass die Implementierungsdetails verborgen sind und nur die Schnittstelle verfügbar gemacht wird. Wenn Ihre Wrapper-Klasse UsingEigen der systemeigenen Bibliothek Eigen kein Verhalten oder keinen Status hinzufügt, ändert sich die Schnittstelle nicht. In diesem Fall sollten Sie diesen Wrapper vollständig löschen und Ihr Programm mit den Datenstrukturen Eigen schreiben.

Das Freilegen einer Matrix oder eines Vektors unterbricht die Kapselung nicht: nur die Implementierung der Matrix oder des Vektors würde dies tun. Die Bibliothek Eigen macht die arithmetischen Operatoren, nicht aber ihre Implementierung verfügbar.

Mit Expression-Vorlagenbibliotheken besteht die häufigste Möglichkeit für Benutzer zum Erweitern der Bibliotheksfunktionalität darin, Verhalten hinzuzufügen und nicht durch Hinzufügen von Status hinzuzufügen. Und für das Hinzufügen von Verhalten müssen Sie keine Wrapper-Klassen schreiben: Sie können auch Nicht-Member-Funktionen hinzufügen, die in Bezug auf die Klassenelementfunktionen Eigen implementiert sind. Siehe this column "Wie Non-Member-Funktionen die Verkapselung verbessern" von Scott Meyers.

Für Ihre Sorge, dass die Umwandlung Ihres aktuellen Programms zu einer Version, die explizit die Eigen Funktionalität verwendet: Sie können die Änderung Schritt für Schritt durchführen, kleine Teile Ihres Programms jedes Mal ändern, stellen Sie sicher, dass Ihr Gerät testen (Sie haben Unit-Tests, oder?), brechen Sie nicht, während Sie weitermachen.

+2

Durch das Aussetzen * von Datenelementen * wird die Kapselung unterbrochen. Aber das Hinzufügen der Überschreibungen der Expression-Templates für die Eigen-Klassen würde es auf die gleiche Weise brechen. –

+0

@KonradRudolph Es kapert die Kapselung nicht, wenn 'UsingEigen' die exakt gleiche Schnittstelle und die exakt gleiche Implementierung hat (d. H. Eine literale Wrapper-Klasse mit reiner Weiterleitung und ohne Protokollierung/Überprüfung etc.). Sie hätten recht, wenn 'UsingEigen' eine zusätzliche Abstraktionsebene definieren würde, aber es scheint nicht der Fall zu sein (und es sollte nicht' UsingEigen' genannt werden, denn das macht die Implementierung unmöglich!) – TemplateRex

-2

Ich verstehe nicht alle Ihre Frage Ich werde versuchen, Sie die meisten von ihnen zu beantworten. In diesem Satz:

UsingEigen operator + (const UsingEigen& adee)const 
    { 
     return UsingEigen(data_ + adee.data_); 
    } 

Sie haben eine Überlastung Operator (sorry ich weiß nicht, ob dies der richtige Weg ist, auf Englisch schreiben) Sie schreiben können, aus diesem Grund:

a = b + c + d; 

anstelle von:

a.data_ = b.data_ + c.data_ + d.data_; 

Sie werden kein Problem haben, Kosten Ihres Programms werden gleich sein. Zusätzlich werden Sie Verkapselung und Effizienz haben.

Auf der anderen Seite, wenn Sie Ihren eigenen Operator definieren möchten, können Sie es tun, wie die Vorlage es tun. Sie können Informationen über die Web-Suche „Überlastung Operator“ zu finden, ist aber ähnlich wie diese:

UsingEigen operator + (const UsingEigen& adee)const 
    { 
     return UsingEigen(data_ + adee.data_); 
    } 

Statt „+“ können Sie den Betreiber setzen können und tun, um die Operationen, die Sie benötigen.

Wenn Sie eine Matrix erstellen möchten, ist es einfach. Sie müssen nur ein Array aus Vektor oder Vektor erstellen.

Ich denke, ist so etwas wie dieses:

std::vector<vector<float>> 

Ich bin nicht sicher, aber es ist leicht, auf der anderen Seite können Sie eine einfache Matrix auf diese Weise verwenden:

float YourMatrix [size] [Größe];

Ich hoffe, es könnte Ihnen helfen. Ich verstehe nicht alle Ihre Frage, wenn Sie etwas mehr brauchen, fügen Sie mich auf Google + und ich werde versuchen, Ihnen zu helfen.

Entschuldigung für mein Englisch, ich hoffe, Sie können alles verstehen und es hilft Ihnen.

+1

Sie leider sind falsch. Sie müssen nachlesen, was [Expression Templates] (http://en.wikipedia.org/wiki/Expression_templates) sind und wie sie diesen Code beeinflussen. Ihre überladenen Operatoren werden die Expression-Templates nicht nutzen, genau wie das OP es beschrieben hat. Außerdem bietet die Eigen-Bibliothek weit mehr Semantik als der naive Nested-Array-Ansatz, den Sie gezeigt haben, was für OP völlig unzureichend ist. –

+0

Vielen Dank Manuel, Wenn ich Ihren Ansatz verwende, wird das Programm kompilieren und korrekt funktionieren. Aber Ausdrücke wie a = b + c + d; wird in etwa so aussehen: zuerst wird b + c berechnet und in einem temporären btemp gespeichert. Dann wird bctemp zu d hinzugefügt und bcdtemp erstellt. Endlich wird der bcdtemp einem a zugewiesen. Das sind 3 Loops und 2 Provisorien. Mein Ziel ist es, dies zu vermeiden. –

+0

@Manuel Wenn Sie interessiert sind, was ich meine, indem Sie die Provisorien und Loops vermeiden, finden Sie hier eine bessere Erklärung http://eigen.tuxfamily.org/dox/TopicInsideEigenExample.html –

2

Meiner Meinung nach sieht dies eher ein objektorientiertes Designproblem als ein Bibliotheksnutzungsproblem aus. Was immer Sie aus den Büchern lesen, sind die richtigen Empfehlungen. d. h., stellen Sie keine Elementvariablen zur Verfügung und schirmen Sie die oberen Schichten von den Nuancen der Verwendung der Schicht der dritten Partei ab.

Worauf Sie sich freuen können, sind richtige Abstraktionen mathematischer Funktionen, die intern mit dieser Bibliothek implementiert werden können. d. h., Sie könnten eine eigene Bibliothek mit Funktionen auf höherer Ebene als elementare Vektor- und Matrixoperationen verfügbar machen. Auf diese Weise können Sie die Besonderheiten der Interaktionen zwischen den Bibliotheksobjekten nutzen und gleichzeitig müssen Sie Ihre Elementvariablen keinen höheren Ebenen zugänglich machen.

Zum Beispiel könnten Sie meine höheren APIs wie die Berechnung der Entfernung von einem Punkt zu einer Ebene, die Entfernung zwischen zwei Ebenen, die Berechnung der neuen Koordinaten eines Punktes in einem anderen Koordinatensystem mit Hilfe der Transformationsmatrizen etc. abstrahieren Methoden intern können Sie die Bibliotheksobjekte nutzen.Sie können festlegen, dass keine Bibliotheksklassen in den API-Signaturen verwendet werden, um Abhängigkeiten für die höheren Ebenen dieser Bibliothek zu vermeiden.

Die oberen Schichten Ihres Programms sollten in der Abstraktionsebene höher sein und brauchen sich nicht um die elementaren Implementierungsdetails zu kümmern, wie zum Beispiel die Berechnung der Entfernung von einem Punkt zur Ebene usw. Sie brauchen es auch nicht wissen, ob diese untere Schicht mit dieser Bibliothek oder etwas anderem implementiert ist. Sie würden nur die Schnittstellen Ihrer Bibliothek verwenden.

Verwandte Themen