webentwicklung-frage-antwort-db.com.de

Funktion auf alle Eigenmatrixelemente anwenden

Ich habe einen Eigen::MatrixXd und ich möchte alle seine Elemente ändern, indem ich eine Funktion komponentenweise wende. Zum Beispiel:

MatrixXd m = ...;

for each m[i][j]:
  m[i][j] = exp(m[i][j]);

Gibt es eine Möglichkeit, dieses Ergebnis zu erreichen?

16
Nick

Ja, benutzen Sie die Eigen::MatrixBase<>::unaryExpr() member Funktion. Beispiel:

#include <cmath>
#include <iostream>

#include <Eigen/Core>

double Exp(double x) // the functor we want to apply
{
    return std::exp(x);
}

int main()
{
    Eigen::MatrixXd m(2, 2);
    m << 0, 1, 2, 3;
    std::cout << m << std::endl << "becomes: ";
    std::cout << std::endl << m.unaryExpr(&Exp) << std::endl;
}
22
vsoftco

Die Antwort von vsoftco ist sehr allgemein und eignet sich gut für benutzerdefinierte Funktionen. Es gibt jedoch einen einfacheren Weg für viele der häufig verwendeten Funktionen. Wenn wir sein Beispiel anpassen, können wir arrays verwenden und es sieht so aus:

#include <iostream>
#include <Eigen/Core>

int main()
{
    Eigen::MatrixXd m(2, 2);
    m << 0, 1, 2, 3;
    std::cout << m << "\nbecomes:\n";
    std::cout << m.array().exp() << std::endl;
    return 0;
}
21
Avi Ginsburg

@ vsoftcos Antwort brachte mich zu 99% auf dieses Problem, aber aus irgendeinem Grund gab ich &Exp an .unaryExpr() weiter, was zu Kompilierungsfehlern führte (g ++, c + 11, Eigen 3.3.5 gab einen Fehler in Bezug auf: base type ‘double (*)(double)’ fails to be a struct or class type).

Ich habe jedoch festgestellt, dass das Erstellen eines std::function-Objekts stattdessen dieses Problem behoben hat. @ Vsoftcos Beispiel kopieren:

#include <cmath>
#include <iostream>

#include <Eigen/Core>

double Exp(double x) 
{
    return std::exp(x);
}

int main()
{
    Eigen::MatrixXd m(2, 2);
    m << 0, 1, 2, 3;
    std::function<double(double)> exp_wrap = Exp; //added to @vsoftco's answer
    std::cout << m << std::endl << "becomes: ";
    std::cout << std::endl << m.unaryExpr(exp_wrap) << std::endl; //and used here
}

Ich bin mir nicht sicher, wie viel Aufwand ein std::function-Objekt (oder std::ptr_fun) im Vergleich zum Weitergeben von &Exp hat, aber ich könnte es nicht schaffen, ohne diese Alternativen zu arbeiten.

Prost

0
KamKam