Mapping Avec Eigen Library [Résolu]

Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
-
Bonjour,


Map (classe de la biblio Eigen ) : "This class represents a matrix or vector expression mapping an existing array of data. It can be used to let Eigen interface without any overhead with non-Eigen data structures, such as plain C arrays or structures from other libraries."

cette expression sert pour introduire mon problème.
En effet, j'ai un tableau 2D qui j'ai obtenu à partir d'un fichier.csv (std::vector<std::vector<double>> TAB1)
j'ai essayé de mapper mon tableau en tant que une matrice (MatrixXd) .

j'ai cette erreur : error: expected primary-expression before 'V1'.
mon code est le suivant :
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
#include <clocale>
#include "EigenResources\Eigenvalues"

using namespace Eigen;

template <class charT, charT sep>
class punct_facet: public std::numpunct<charT> {
protected:
  charT do_decimal_point() const { return sep; }
};

double comaStod(std::string const& s)
{
  std::istringstream iss(s);
  iss.imbue(std::locale(std::cout.getloc(), new punct_facet<char, ','>));
  double d;
  if (!(iss >> d))
    throw std::invalid_argument("invalid double");

  return d;
}

int main()
{
  const std::string filename = "Measurements.csv";
  std::ifstream file(filename);

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  std::string line;
  std::vector<std::vector<double>> TAB1;
  while (std::getline(file, line))
  {
    
    std::vector<double> v;
    std::string field;
    std::stringstream ss(line);
    while (std::getline(ss, field, ';'))
    {
      try
      {
        v.push_back(comaStod(field));

      }
      catch (std::invalid_argument& e)
      {
        std::cerr << "Can't convert " << field << " to double (" << e.what() << ")" << std::endl;
        continue;
      }
    }
    if (!v.empty())
      TAB1.push_back(v);
  }

  /*std::cout << "Vec:\n";
  for (auto& vec : array)
  {
   for (auto& value : vec)
     std::cout << value << " ";
    std::cout << std::endl;
  }*/

  //affichage (deux boucles for)

  std::cout << "Vec:\n";
  for (size_t i=0; i<TAB1.size(); ++i)
    {
        for (size_t j=0; j<TAB1[i].size(); ++j)
        {
              std::cout << TAB1[i][j] << " ";
        
            std::cout<< Map <MatrixXd> V1(TAB1.data())<<std::endl; //mapping
        }

        std::cout << "\n";
    }

  
  return 0;
}



Je suis incapable de savoir pourquoi j'ai cette erreur si quelqu'un a une idée je suis preneuse :)

Merci d'avance
Afficher la suite 

Votre réponse

15 réponses

Meilleure réponse
Messages postés
366
Date d'inscription
dimanche 7 février 2016
Dernière intervention
21 novembre 2018
1
Merci
Pour gérer les complexes, il faut voir ce que la classe
std::complex<double>
offre.
 j 
n'est qu'une variable, on peut utiliser à la place
 std::complex<double{0,1} 
ou bien depuis le C++14 après avoir indiqué
 using namespace std::literals; 
on peut utiliser
 1i 
.
On a donc :
Eigen:: Matrix3cd  Z;
const std::complex<double>  j{ 0 , 1 };
Z(0,0) = res1_ohm[0] + j * res2_ohm[0];
// ou
Z(0,0) = std::complex<double>{ res1_ohm[0] , res2_ohm[0] };
// ou
using namespace literals;
Z(0,0) = res1_ohm[0] + 1i * res2_ohm[0];

Merci Dalfab 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CodeS-SourceS

Codes Sources a aidé 105 internautes ce mois-ci

Commenter la réponse de Dalfab
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Bonjour.

Pour convertir un std::vector de std::vector en Matrice, il faut le faire "à la main", tu ne trouveras pas de méthode toute faite. Soit ta matrice est carrée et tu connais ses dimensions, et c'est facile à faire. Soit tu ne sais pas à quoi ressemble ta matrice, et tu n'as pas ses dimensions par avance, et là c'est plus compliqué.
J'ai considéré le deuxième cas (qui fonctionne aussi pour le premier) vu que tu lis à partir d'un fichier. J'ai donc écris une fonction de conversion générique. Si la matrice n'a pas ses lignes avec le même nombre de colonnes, 0 sera mis dans les "trous".

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
#include <clocale>
#include <complex>
#include <cmath>
#include <algorithm>
#include <Eigen/Dense>

template <class charT, charT sep>
class punct_facet: public std::numpunct<charT> {
protected:
  charT do_decimal_point() const { return sep; }
};

double comaStod(std::string const& s)
{
  std::istringstream iss(s);
  iss.imbue(std::locale(std::cout.getloc(), new punct_facet<char, ','>));
  double d;
  if (!(iss >> d))
    throw std::invalid_argument("invalid double");

  return d;
}

// Will convert any vector of vector to Eigen::Matrix, but it's slow...
Eigen::MatrixXd convertToEigenMatrix(const std::vector<std::vector<double>>& array)
{
  // Search max_col_size
  size_t max_col_size = 0;
  for (size_t row = 0; row < array.size(); ++row)
    max_col_size = std::max(max_col_size, array[row].size());

  Eigen::MatrixXd matrix(array.size(), max_col_size);
  for (size_t row = 0; row < array.size(); ++row)
  {
    for (size_t col = 0; col < array[row].size(); ++col)
      matrix(row, col) = array[row][col];
    // Fill any too short columns with 0.
    for (size_t col = array[row].size(); col < max_col_size; ++col)
      matrix(row, col) = 0;
  }

  return matrix;
}

int main()
{
  const std::string filename = "Measurements.csv";
  std::ifstream file(filename);

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  std::string line;
  std::vector<std::vector<double>> array;
  while (std::getline(file, line))
  {
    // Ignore line starting with #
    if (line.empty() || line[0] == '#')
      continue;

    std::vector<double> v;
    std::string field;
    std::stringstream ss(line);
    while (std::getline(ss, field, ';'))
    {
      try
      {
        v.push_back(comaStod(field));
      }
      catch (std::invalid_argument& e)
      {
        //std::cerr << "Can't convert " << field << " to double (" << e.what() << ")" << std::endl;
        continue;
      }
    }

    if (!v.empty())
      array.push_back(v);
  }

  auto matrix = convertToEigenMatrix(array);
  std::cout << "Nb rows: " << matrix.rows() << ", nb cols: " << matrix.cols() << ", total size: " << matrix.size() << std::endl;
  std::cout << "Matrix:\n" << matrix << std::endl;

  return 0;
}



Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
je te remercie pour ta réponse :)
de mon coté j'ai essayé le prog suivant, il m'a donné des bon résultats mais je sais pas il vaut mieux utiliser mon code ou bien le tien ?
voici mon code:
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
#include <clocale>
#include <cmath>
#include <complex>
#include "EigenResources\Eigenvalues"

template <class charT, charT sep>
class punct_facet: public std::numpunct<charT> {
protected:
  charT do_decimal_point() const { return sep; }
};
//conversion , to .
double comaStod(std::string const& s)
{
  std::istringstream iss(s);
  iss.imbue(std::locale(std::cout.getloc(), new punct_facet<char, ','>));
  double d;
  if (!(iss >> d))
    throw std::invalid_argument("invalid double");

  return d;
}

//Eigen Matrix 

Eigen::MatrixXd ConvertToEigenMatrix(std::vector<std::vector<double>> data)
{
    Eigen::MatrixXd eMatrix(data.size(), data[0].size());
    for (int i = 0; i < data.size(); ++i)
        eMatrix.row(i) = Eigen::VectorXd::Map(&data[i][0], data[0].size());
    return eMatrix;
}

int main()
{
  const std::string filename = "Measurements.csv";
  std::ifstream file(filename);

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  std::string line;
  std::vector<std::vector<double>> TAB1;
  while (std::getline(file, line))
  {
    // Ignore line starting with #
    //if (line.empty() || line[0] == '#')
      //continue;
    std::vector<double> v;
    std::string field;
    std::stringstream ss(line);
    while (std::getline(ss, field, ';'))
    {
      try
      {
        v.push_back(comaStod(field));

      }
      catch (std::invalid_argument& e)
      {
        std::cerr << "Can't convert " << field << " to double (" << e.what() << ")" << std::endl;
        continue;
      }
    }
    if (!v.empty())
      TAB1.push_back(v);
  }

  //affichage (deux boucles for)

  std::cout << "Vec:\n";
  for (size_t i=0; i<TAB1.size(); ++i)
    {
        for (size_t j=0; j<TAB1[i].size(); ++j)
        {
              //std::cout << TAB1[i][j] << " ";
             
        }
         std::cout << "\n";
    }
 //appel de la fonction pour la conversion Eigen Matrix
 Eigen::MatrixXd ma_matrice;
 ma_matrice = ConvertToEigenMatrix (TAB1);
 std::cout << ma_matrice <<std::endl;

  return 0;
}



une question bête : pourquoi t'as ajouté const ici Eigen::MatrixXd convertToEigenMatrix(const std::vector<std::vector<double>>& array)??

Merci :)
Commenter la réponse de cppcdb
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
C'est ce que je t'ai dis dans mon précédent post: La fonction que utilises est bien si tu es sûr que ta structure est fixe. Si elle ne l'est pas, vu qu'aucune erreur n'est gérée, ton programme plantera (au mieux) ou fera n'importe quoi.
La fonction que je te propose permet d'être plus flexible. Le programme ne plantera jamais, mais tu peux avoir des colonnes à 0, si le format lu est incorrect.
Enfin, la meilleure solution serait peut être de vérifier le format attendu et de prévenir si celui-ci est incorrect (en d'autre terme faire échouer le programme si la matrice n'est pas "rectangulaire" et entièrement remplie).

une question bête : pourquoi t'as ajouté const ici Eigen::MatrixXd convertToEigenMatrix(const std::vector<std::vector<double>>& array)??

Il n'y a pas de modification de array, donc on le marque comme n'étant pas modifiable. C'est une sécurité, car en mettant const, j'ai l'assurance que la fonction ne pourra pas modifier array.


Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
je te remercie pour ta réponse détaillée et très claire ;)
Commenter la réponse de cppcdb
0
Merci
Bonjour,

une question concernant la multiplication vecteur élément par élément.
expl :
V 1 = (1,2,3) V2 = (4,5,6) V3 = V1*V2 = (4,10,18)

j'ai essayé d'appliquer cette opération avec mes vecteurs colonnes en utilisant une boucle for . Mais j'ai eu cette erreur :" Assertion failed: index >= 0 index < size(), file c:\Users\Desktop\Projet1\EigenResources\src/core/DenseCoeffsBase/h, Line 408"
est ce que cette erreur signifie que j'ai dépassé la taille de mon vecteur ?

Merci :)

ci dessous mon code :
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
#include <clocale>
#include <complex>
#include <cmath>
#include <algorithm>
#include <Eigen/Dense>

template <class charT, charT sep>
class punct_facet: public std::numpunct<charT> {
protected:
  charT do_decimal_point() const { return sep; }
};

double comaStod(std::string const& s)
{
  std::istringstream iss(s);
  iss.imbue(std::locale(std::cout.getloc(), new punct_facet<char, ','>));
  double d;
  if (!(iss >> d))
    throw std::invalid_argument("invalid double");

  return d;
}

// Will convert any vector of vector to Eigen::Matrix, but it's slow...
Eigen::MatrixXd convertToEigenMatrix(const std::vector<std::vector<double>>& array)
{
  // Search max_col_size
  size_t max_col_size = 0;
  for (size_t row = 0; row < array.size(); ++row)
    max_col_size = std::max(max_col_size, array[row].size());

  Eigen::MatrixXd matrix(array.size(), max_col_size);
  for (size_t row = 0; row < array.size(); ++row)
  {
    for (size_t col = 0; col < array[row].size(); ++col)
      matrix(row, col) = array[row][col];
    // Fill any too short columns with 0.
    for (size_t col = array[row].size(); col < max_col_size; ++col)
      matrix(row, col) = 0;
  }

  return matrix;
}

int main()
{
  const std::string filename = "Measurements.csv";
  std::ifstream file(filename);

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  std::string line;
  std::vector<std::vector<double>> array;
  while (std::getline(file, line))
  {
    std::vector<double> v;
    std::string field;
    std::stringstream ss(line);
    while (std::getline(ss, field, ';'))
    {
      try
      {
        v.push_back(comaStod(field));
      }
      catch (std::invalid_argument& e)
      {
        //std::cerr << "Can't convert " << field << " to double (" << e.what() << ")" << std::endl;
        continue;
      }
    }

    if (!v.empty())
      array.push_back(v);
  }

  auto matrix = convertToEigenMatrix(array);
  std::cout << "Nb rows: " << matrix.rows() << ", nb cols: " << matrix.cols() << ", total size: " << matrix.size() << std::endl;
  std::cout << "Matrix:\n" << matrix << std::endl;

// Vecteurs colonnes : 
Eigen:: VectorXd R2,r2;
R2 = matrix.col(2); //2éme colonnes de la matrice
//Multiplication element par element du vecteur R2:
for (int k=0; k< R2.size(); ++k)
{
r2[k]=R2[k]*R2[k];
} 

  return 0;
}

Commenter la réponse de cppcdb
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Nommer ses variables R2 et r2, c'est une très très mauvaise idée :).
Évite les majuscules, et les noms de variables identiques qui ne diffèrent que par leur casse. C'est un bon moyen de vite s'emmêler. D'une manière générale, essaie de donner un nom explicite à tes variables. Une lettre simple n'étant pas super claire (sauf pour des index par exemple).

Pour répondre à ta question, "R2" existe et à une taille, mais "r2" n'est pas initialisé, et a vraisemblablement une taille de 0. Il te faut donc lui donner une taille, et vérifier quand tu utilises des index que ceux-ci soient compatibles avec ce que tu utilises (c'est-à-dire par hors bornes).


Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu
0
Merci
oui t'as raison :)
c'est bon j'ai donné des noms explicites à mes variables
et j'ai déclaré la taille de mon vecteur et ça marche très bien
je te remercie :)
Commenter la réponse de cppcdb
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
Bonjour,
est ce qu'il y a une autre manière pour créer une matrice complexe avec Eigen à part la méthode que j'ai utilisé ci dessous?
(j'ai pas mis le code entier et je sais pas est ce que je peux poser cette question ici ou bien je dois créer un nouveau sujet )

Merci :)

Eigen::Matrix3cd matrice_Z1;

matrice_Z1.real()<<res1_ohm[0],0,0,0,res2_ohm[0],0,0,0,res3_ohm[0]; //partie réelle
matrice_Z1.imag()<< pulsation[0]*induc1_henry[0],pulsation[0]*mutuelle12[0],pulsation[0]*mutuelle13[0],pulsation[0]*mutuelle12[0],pulsation[0]*induc2_henry[0],pulsation[0]*mutuelle23[0],pulsation[0]*mutuelle13[0],pulsation[0]*mutuelle23[0],pulsation[0]*induc3_henry[0]; // partie imaginaire
std::cout << "la matrice Z: "<< matrice_Z1 << est::endl;
Commenter la réponse de cppcdb
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Je ne sais pas trop ce que tu cherches et je ne connais pas bien Eigen (j'ai lu la documentation pour la première fois suite à ton post).

D'après la documentation, tu as une initialisation comme tu l'as faite (avec des ","), et il y a une prédéclaration (tu donnes la tailles de ta matrice et tu remplis les cases comme suit: matrice(i, j) = valeur).
Commenter la réponse de cptpingu
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
Oui tout à fait, on peut remplir les cases de cette façon : matrice (i,j) = val, mais vu que j'ai des nombres complexes (a+jb) j'ai pas pu utiliser cette écriture. J'ai essayé de faire comme suit:

Eigen:: Matrix3cd matrice_Z;
Z(0,0)= res1_ohm[0]+j * res2_ohm[0];


Et j'ai eu un msg d'erreur : 'j' was not declared in this scope.
En tous cas les fonctions .real et .imag m'ont donné des bons résultats :)
je te remercie :)
Commenter la réponse de cppcdb
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Ton message d'erreur veut juste dire que "j" n'existe pas, ce n'est pas lié aux matrices ou aux nombres complexes.
Commenter la réponse de cptpingu
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
dans ce cas je dois déclarer "j" c'est ça ?
si je vais déclarer "j", je vais le déclarer comme quoi ? quel type ?
Commenter la réponse de cppcdb
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Je n'en ai aucune idée. Je peux aider techniquement, mais je ne peux pas deviner tes intentions. Tu es la personne la mieux placée pour savoir ce que tu cherches à réaliser.
Commenter la réponse de cptpingu
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
je vais travailler avec .real et .imag :p
c plus simple :D
merci :)
Commenter la réponse de cppcdb

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.