[C++] fonction de calcul de min d'une matrice

Résolu/Fermé
chreks - 2 mai 2007 à 21:22
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 - 3 janv. 2008 à 21:43
Bonjour,
je serais très content si quelqu'un pourrez m'aidez a resoudre ce problème
en fait j'ai un fichier ou il ya ces données
0: (1,0) (2,0) (3,5) (4,2) (5,8) (6,3) (7,2) (8,4)
1: (0,0) (2,0) (3,8) (4,4) (5,1) (6,7) (7,5) (8,3)
2: (0,0) (1,0) (3,7) (4,4) (5,2) (6,2) (7,3) (8,6)
3: (4,0) (5,0) (0,5) (1,8) (2,7) (6,2) (7,6) (8,8)
4: (3,0) (5,0) (0,2) (1,4) (2,4) (6,3) (7,9) (8,1)
5: (3,0) (4,0) (0,8) (1,1) (2,2) (6,6) (7,7) (8,9)
6: (7,0) (8,0) (0,3) (1,7) (2,2) (3,2) (4,3) (5,6)
7: (6,0) (8,0) (0,2) (1,5) (2,3) (3,6) (4,9) (5,7)
8: (6,0) (7,0) (0,4) (1,3) (2,6) (3,8) (4,1) (5,9)

c'est une matrice dont je récupere les données avec une structure map pour la matrice et donc j'aimerais faire des calculs sur cette matrice .

Chaque ligne d'un fichier correspond à une ligne de la matrice et se
présente sous la forme :
<n°ligne>:\tab(<n°colonne>,<coefficient>)\tab(<n°colonne>,<coefficient>)\tab(<n°colonne>,<coefficient>)...

donc après récuperation des donnéesde la forme m[i][j] je dois calculer un nombre :
d'abord pour une ligne je dois trouver le minimum entre les 3 premiers et l'ajouter au minimum entre les 3 suivant (donc une boucle 3 par 3 sur j)ce qui donne une somme s1
après la fin de la ligne je dois refaire le procédé pour la seconde ligne => s2 et ensuite la 3 eme ligne => s3 ( donc boucle 3par 3 sur i)
après je dois choisir le minimum entre la 1 ere ligne , la deuxime et la 3eme c'est a dire entre s1,s2,s3
et après je pourrais passer a la 4 ligne pour refaire de meme entre les 3 colonnes et les 3 lignes .

j'ai programmé une petite fonction que j'ai testé mais j'ai un probléme : explication :

int MINIMUM (int valeur1 , int valeur2 , int valeur3 ) { 
 //fonction de calcul de minimum
int Min = valeur1 ; 

if ( Min > valeur2){
	Min = valeur2;
	if (Min>valeur3){
		Min = valeur3;
	}
}
if(Min>valeur3){
		Min = valeur3;	
	}
return Min;
}

//calcul du head // programme a faire!!!
int calcul_head(matrix_t m){
    int a1,a2,a3,s1,s2,s3,S,head,ss;
    s1=0;
    s2=0;
    s3=0;
    head=0;
    
    for(int i=0;i<9;i=i+3)//m.size()
    {
	for(int j=0;j<9 ; j=j+3)
	{
	    a1 = MINIMUM( m[i][j],m[i][j+1],m[i][j+2]);
	    a2 = MINIMUM( m[i+1][j],m[i+1][j+1],m[i+1][j+2]); 
	    a3 = MINIMUM( m[i+2][j],m[i+2][j+1],m[i+2][j+2]);
	    
	     s1 = s1+ a1;
	     s2 =  s2 +a2;
	     s3 =  s3+a3;
	    
	   		
	     //   std::cout<<"s1 = "<<s1<<std::endl;
	     // std::cout<<"s2 = "<<s2<<std::endl;
	     //std::cout<<"s3 = "<<s3<<std::endl;
	}
	
	
	S = MINIMUM(s1,s2,s3);
	std::cout<<"S = "<< S<<std::endl;    
	    head = head +S;
	    
    }
    return head/2;
}


pour la matrice donné au début je dois trouver head = 11
en fait l'erreur est que s1 calcule les min de la 1ere ligne et l'ajoute au min de la 4eme ligne alors qu'il faudrait ajouter la ligne minimum entre les 3 premieres lignes a la ligne minimum des 3 suivantes et ainsi de suite jusqu'a trouver le head et le diviser par 2.

je vous remerci beaucoup pour votre aide qui me sera d'une grande utilité surtout que j'ai fait un tout petit peu de C++.
A voir également:

20 réponses

je suis content que tu ai le temps de me faire tout ca. et je pense que tu a bien compris ce que je te demandais. je t'en remercie enormément.

j'ai essayé de bien comprendre comment récuperer les valeur de la matrice avec les clés! je ne savais pas qu'on pouvait faire de cette manière,j'apprend des choses merci !!
j'ai compris globalement le programme j'ai vu que la sparse matrix etait une sous classe de map(..,map(..)) et que index_sparse_matrix etait une autre soous classe de la sparsmatrix. donc globalement ca va!
par contre le programme d'avant , je l'utilise ici , donc toutes les données de la matrice je les récupere d'un fichier, dont on voit l'exemple en haut,avec les fonctions de l'autre post!

et je n'arrive pas à inserer les fonctins de lecture de fichier dans le programme car la déclaration de la map dans les fonctions n'est pas la meme que dans les classe ou on utilise des Tkey1, Tkey2 et des template sur Tdata.

donc merci de pouvoir m'inserer ces focntions dans le programme pour pouvoir calculer le head de la matrice se trouvant dan le fichier et non pas celle crée par la fonction set!

par ailleurs, pour utiliser les donnees de la matrice, tu m'a dis qu'on n'utilisait pas les opérateurs [][]mais plutot la fonction get(..) .
j'ai pas vraiment bien compris puisque pour les calcul m[][]=0 pour des valeurs non existante !mais peut etre c'est une matrice pleine qui pren de la memoire?? et donc comme je vous ai di , je veu utilisé les donné du fichier et non pas la focntion set ,mais on peut la garder quand meme, sera peut etre utile! ;)

probleme: inserser ce code en bas dans le programme en haut!
#include <fstream>
#include <iostream>
#include <string>
#include <map>

// une matrice creuse d'entiers
typedef std::map<unsigned,std::map<unsigned,int> > matrix_t;

extern "C"{
#include <stdio.h> 
#include <string.h>
}

bool lire_ligne(const std::string & line,matrix_t & matrix){
    const char *str = line.c_str();
    char *buffer = (char *)malloc(sizeof(char)*(line.size()+1));
    strcpy(buffer,str);
    unsigned ligne=0;
    unsigned colonne=0;
    int valeur;
    char *sep = "()";
    char *maillon, *brkt;

    if(sscanf(buffer," %i : ",&ligne)!=1){
        free(buffer);
        return false;
    }
    strtok_r(buffer,":", &brkt);
//  std::cout << " :  >> buffer = " << buffer << std::endl;
//  std::cout << " :  >> brkt = " << brkt << std::endl;
    for (maillon = strtok_r(brkt, sep, &brkt); maillon; maillon = strtok_r(NULL, sep, &brkt)){
	//   printf("maillon = [%s] \n", maillon);
        int res = sscanf(maillon,"%i,%d ",&colonne,&valeur);
        if(res == 2) matrix[ligne][colonne] = valeur;
    }

    free(buffer);
    return true;
}



bool lire_fichier(const char *filename,matrix_t & matrix){
    std::ifstream f(filename);
    if (f){
        std::cout << "Lecture de [" << filename << ']' << std::endl;
        std::string line;
        for(unsigned noline=1;std::getline(f,line);++noline){
            if(line.empty()) continue;
            if(!lire_ligne(line,matrix)){
                std::cerr << "Erreur : ligne invalide : ligne " << noline << ": "
                    << line << std::endl;
                return false; // on arrê la lecture
            }
        }
        return true; // lecture ok
    }
    std::cerr << "Ne peut ouvrir [" << filename << ']' << std::endl;
    return false; // le fichier n'existe pas ou ne peut êe ouvert
}


int main(){
    const char *filename="test.txt";
    matrix_t m;
    int min;

    // Lire le fichier
    if(!lire_fichier(filename,m)){
        std::cerr << "Le contenu du fichier [" << filename << "] est invalide " << std::endl;
        return 1;
    }
	
    // Afficher la matrice
    {
        std::map<unsigned,std::map<unsigned,int> >::const_iterator
            mit1(m.begin()),mend1(m.end());
        for(;mit1!=mend1;++mit1){
            const unsigned & ligne = mit1->first;
            const std::map<unsigned,int> & ligne_matrice = mit1->second;
            std::map<unsigned,int>::const_iterator
                mit2(ligne_matrice.begin()),mend2(ligne_matrice.end());
            for(;mit2!=mend2;++mit2){
                const unsigned & colonne = mit2->first;
                const int & valeur = mit2->second;
                std::cout <<'(' << ligne << ',' << colonne << ") = " << valeur << std::endl;
            }
        }std::cout<< " m[2][1160]  =    "<<m[2][1]<< std::endl; 
    }


 
   return 0;
}


de plus pour le calcul du head,la valeur qui nous interesse c'est la derniere après que toutes les iterations soit faites si j'ai bien compris, je n'arrive pas a la récuperer toute seule!! :s

en tout cas merci pour tout!! vraiment merci.
1
bonjour!!!!!!
pouvez-vous m'ecrir le code complet d'un "programme c++ avec des classe et des fonctions simple" qui permet de remplir,d'ajouter et de supprimer et d'afficher la matrice creuse suivante(avec des commentaires//):
0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 7 0 0 1 2 0 2
....................

ligne:2, 2
colun: 2, 5
valeur:7, 12

je vais vous donner l'exemple de la fonction qui affiche les éléments d'indice 1 séparés par des";":
*******************************************
void matrice creuse::coutLigne(unsigned ligne )
{
valeurSignificative * vs=Ligs[ligne];
for (unsigned colonne=0; colonne< NBCOLS; colonne++)
{
if (vs && vs->col==colonne)
{
cout<<vs->val<<", ";
vs=vs-> suivMenLigne;
}
else
cout<<"0, ";
}
*******************************************
1
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
3 mai 2007 à 02:40
1) Si c'est une matrice stockée dans une map de map c'est un stockage de type "matrice creuse" et auquel cas m[i] (et à fortiori m[i][j]) n'existe pas dans le cas général. Tu peux définir une fonction qui fait 2 find (un sur i puis un sur j) dans cette map et qui retourne une valeur par défaut (genre 0) si la case [i][j] n'existe pas. Voici une classe de matrice creuse que je te propose :
#ifndef SPARSE_MATRIX
#define SPARSE_MATRIX

#include <map>

/*
 * Tkey1 : type de la clé d'une ligne
 * Tkey2 : type de la clé d'une colonne
 * Tdata : type des datas stockées dans la matrice
 */
template <typename Tkey1,typename Tkey2,typename Tdata>
class sparse_matrix_t : public std::map<Tkey1,std::map<Tkey2,Tdata> >{
    public:
    typedef std::map<Tkey2,Tdata> row_t;
    typedef std::map<Tkey1, row_t> matrix_t;

    /**
     * \brief Récuperer un terme dans une matrice 2D creuse
     * \param k1 La clé de la ligne
     * \param k2 La clé de la colonne
     * \return La valeur stockée dans la matrice creuse. Si la case n'existe
     * pas on retourne la donnée obtenue avec le constructeur par défaut.
     */
    Tdata get(const Tkey1 & k1,const Tkey1 & k2) const {
        typename matrix_t::const_iterator f1(this->find(k1));
        if(f1 == this->end()) return Tdata(); // ligne pas dans la matrice
        const row_t & r = f1->second; // la ligne trouvée
        typename row_t::const_iterator f2(r.find(k2));
        if(f2 == r.end()) return Tdata(); // ligne pas dans la matrice
        return f2->second; // terme trouvé
    }
};

#endif

Exemple d'utilisation (fichier plop.cpp) :
#include <iostream>
#include "sparse_matrix.hpp"

int main(){
    /*
     * Une matrice creuse de réels.
     * Clé de la ligne : un entier positif
     * Clé de la colonne : un entier positif
     */
    sparse_matrix_t<unsigned,unsigned,double> m;
    m[0][2] = 6.9;
    m[5][2] = 2.8;
    m[3][7] = 3.7;
    std::cout << "get(m,0,2) = " << m.get(0,2) << std::endl;
    std::cout << "get(m,5,2) = " << m.get(5,2) << std::endl;
    std::cout << "get(m,3,7) = " << m.get(3,7) << std::endl;
    std::cout << "get(m,3,4) = " << m.get(3,4) << std::endl;
    return 0;
}

Donne à l'exécution :
(mando@aldur) (~) $ g++ -W -Wall plop.cpp
(mando@aldur) (~) $ ./a.out
get(m,0,2) = 6.9
get(m,5,2) = 2.8
get(m,3,7) = 3.7
get(m,3,4) = 0

2) Ensuite quand tu parles de blocs de 3 coefficients j'imagine que ce sont des cases adjacentes dans la matrice "pleine" ? Pourquoi t'arrêtes-tu à la case 9 ?

3) Enfin je ne comprends pas pourquoi tu traites les lignes 3 par 3.

Bonne chance
0
bonjour mamiemando,
c'est encore toi qui va m'aider passer ce problème!
je ne sais si tu te rappelle de moi mais c'était toi qui m'avait aidé à faire un programme de lecture de fichier sous forme de map!
c'était justement une matrice creuse! le sujet était lecture de fichier et récup de data.je t'en remercie beaucoup d'ailleurs.
cependant lors de mes calculs sur la matrice j'ai eu un problème que j'ai expliqué plus haut.

Pour revenir sur le sujet de matrice creuse! j'ai bien vérifié que lorsque m[i][j] n'existais pas , le programme retourne 0 comme valeur donc ca m'arrange aussi.

je parlais bien sur de cases adjacentes pour le blo de 3 coefficients
je m'arrete a la case 9 parce que le fichier fourni comme exemple comporte que 9 case. mais je sais qu'il faudrait changer par "m.size()" mais quand j'ai essayé ca ne marche pas !!!

enfin je traite les lignes 3 par 3 parce que je travaille sur des bloc de 3x3.mai bon je pensais que c'était une bonne facon de faire , comme ca a la fin du traitement je pourrais les comparer et ajouter les plus petites d'entres elles. mais je sais pa si tu a bien compri le but du sujet.

mais si tu as un meuilleur programme a me proposer je serai très content car je connais deja la qualité de tes programmes vu que je travaille sur la base de ce que tu m'avais deja donné. merci.

sinon je sais pas si tu a bien compris ce que je voulais exactement faire?
je dois absolument résoudre ce probleme au plus vite car j'en ai passé du temps dessus. et si tu pouvais m'aider, je te serai très reconnaissant. et merci beaucoup.

récapitul:
d'abord pour une ligne i je dois trouver le minimum entre les 3 premiers et l'ajouter au minimum entre les 3 suivant (doncj'ai proposé une boucle 3 par 3 sur j)et ainsi de suite...
ensuite après la fin de la ligne je dois refaire le procédé pour la seconde ligne et ensuite la 3ieme, après je dois comparer entre les 3 premieres ligne et choisir la min d'entre elle et la stoker dans HEAD.
je dois refaire le procede pour les lignes suivantes . et entre temps je dois stocker dan head la somme des lignes minimal de chaque bloc de 3 ligne ( dan lesquelle on choisi que d valeur mini entre chake coeff) .

donc voila le but du programme. ce que j'ai fait ne marche pas bien car comme je l'ai expliqué :
//calcul du head // programme a faire!!!
int calcul_head(matrix_t m){
int a1,a2,a3,s1,s2,s3,head;
s1=0;
s2=0;
s3=0;
head=0;

for(int i=0;i<9;i=i+3)//m.size()
{
for(int j=0;j<9 ; j=j+3)
{
a1 = MINIMUM( m[i][j],m[i][j+1],m[i][j+2]);
a2 = MINIMUM( m[i+1][j],m[i+1][j+1],m[i+1][j+2]);
a3 = MINIMUM( m[i+2][j],m[i+2][j+1],m[i+2][j+2]);

s1 = s1+ a1;
s2 = s2 +a2;
s3 = s3+a3;


// std::cout<<"s1 = "<<s1<<std::endl;
// std::cout<<"s2 = "<<s2<<std::endl;
//std::cout<<"s3 = "<<s3<<std::endl;
}


S = MINIMUM(s1,s2,s3);
std::cout<<"S = "<< S<<std::endl;
head = head +S;

}
return head/2;
}

" en fait l'erreur est que s1 calcule les min de la 1ere ligne et l'ajoute au min de la 4eme ligne alors qu'il faudrait ajouter la ligne minimum entre les 3 premieres lignes a la ligne minimum des 3 suivantes et ainsi de suite jusqu'a trouver le head et le diviser par 2. "

j'espere que tu pourra trouver du temps pour m'aider. je te remercie beaucoup.
si tu veux que je te passe tout le programme pour que tu puisse tester. dis le moi.
merci encore.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
bonjour mamiemando,
c'est encore toi qui va m'aider passer ce problème!
je ne sais si tu te rappelle de moi mais c'était toi qui m'avait aidé à faire un programme de lecture de fichier sous forme de map!
c'était justement une matrice creuse! le sujet était lecture de fichier et récup de data.je t'en remercie beaucoup d'ailleurs.
cependant lors de mes calculs sur la matrice j'ai eu un problème que j'ai expliqué plus haut.

Pour revenir sur le sujet de matrice creuse! j'ai bien vérifié que lorsque m[i][j] n'existais pas , le programme retourne 0 comme valeur donc ca m'arrange aussi.

je parlais bien sur de cases adjacentes pour le blo de 3 coefficients
je m'arrete a la case 9 parce que le fichier fourni comme exemple comporte que 9 case. mais je sais qu'il faudrait changer par "m.size()" mais quand j'ai essayé ca ne marche pas !!!

enfin je traite les lignes 3 par 3 parce que je travaille sur des bloc de 3x3.mai bon je pensais que c'était une bonne facon de faire , comme ca a la fin du traitement je pourrais les comparer et ajouter les plus petites d'entres elles. mais je sais pa si tu a bien compri le but du sujet.

mais si tu as un meuilleur programme a me proposer je serai très content car je connais deja la qualité de tes programmes vu que je travaille sur la base de ce que tu m'avais deja donné. merci.

sinon je sais pas si tu a bien compris ce que je voulais exactement faire?
je dois absolument résoudre ce probleme au plus vite car j'en ai passé du temps dessus. et si tu pouvais m'aider, je te serai très reconnaissant. et merci beaucoup.

récapitul:
d'abord pour une ligne i je dois trouver le minimum entre les 3 premiers et l'ajouter au minimum entre les 3 suivant (doncj'ai proposé une boucle 3 par 3 sur j)et ainsi de suite...
ensuite après la fin de la ligne je dois refaire le procédé pour la seconde ligne et ensuite la 3ieme, après je dois comparer entre les 3 premieres ligne et choisir la min d'entre elle et la stoker dans HEAD.
je dois refaire le procede pour les lignes suivantes . et entre temps je dois stocker dan head la somme des lignes minimal de chaque bloc de 3 ligne ( dan lesquelle on choisi que d valeur mini entre chake coeff) .

donc voila le but du programme. ce que j'ai fait ne marche pas bien car comme je l'ai expliqué :
//calcul du head // programme a faire!!!
int calcul_head(matrix_t m){
int a1,a2,a3,s1,s2,s3,head;
s1=0;
s2=0;
s3=0;
head=0;

for(int i=0;i<9;i=i+3)//m.size()
{
for(int j=0;j<9 ; j=j+3)
{
a1 = MINIMUM( m[i][j],m[i][j+1],m[i][j+2]);
a2 = MINIMUM( m[i+1][j],m[i+1][j+1],m[i+1][j+2]);
a3 = MINIMUM( m[i+2][j],m[i+2][j+1],m[i+2][j+2]);

s1 = s1+ a1;
s2 = s2 +a2;
s3 = s3+a3;


// std::cout<<"s1 = "<<s1<<std::endl;
// std::cout<<"s2 = "<<s2<<std::endl;
//std::cout<<"s3 = "<<s3<<std::endl;
}


S = MINIMUM(s1,s2,s3);
std::cout<<"S = "<< S<<std::endl;
head = head +S;

}
return head/2;
}


" en fait l'erreur est que s1 calcule les min de la 1ere ligne et l'ajoute au min de la 4eme ligne alors qu'il faudrait ajouter la ligne minimum entre les 3 premieres lignes a la ligne minimum des 3 suivantes et ainsi de suite jusqu'a trouver le head et le diviser par 2. "

j'espere que tu pourra trouver du temps pour m'aider. je te remercie beaucoup.
si tu veux que je te passe tout le programme pour que tu puisse tester. dis le moi.
merci encore.

désolé j'ai posté le msg 2 fois!!
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
10 mai 2007 à 18:40
Peux tu me donner l'adresse de l'autre post qu'on supprime celui-ci, qui n'est pas à sa place ?
0
chreks > mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024
10 mai 2007 à 20:05
c prog lecture et recup de data

voila l'adresse du premier post!
merci
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
10 mai 2007 à 22:59
Ah oui ! Je me souviens. Bon je viens de capter pourquoi tu fonctionnais par bloc de trois. J'espère avoir bien compris ce que tu voulais calculer
#include <iostream>
#include <map>
#include <list>

template <typename Tkey1,typename Tkey2,typename Tdata>
class sparse_matrix_t : public std::map<Tkey1,std::map<Tkey2,Tdata> >{
    public:
        typedef std::map<Tkey2,Tdata> row_t;
        typedef std::map<Tkey1,row_t> matrix_t;

        // Recuperer une valeur
        inline Tdata get(const Tkey1 & k1,const Tkey1 & k2) const {
            typename matrix_t::const_iterator f1(this->find(k1));
            if(f1 == this->end()) return Tdata();
            const row_t & r = f1->second;
            typename row_t::const_iterator f2(r.find(k2));
            if(f2 == r.end()) return Tdata();
            return f2->second;
        }

};

// Une classe de matrice creuse indexée (les deux clés sont des entiers positifs)
template <typename Tdata>
class indexed_sparse_matrix_t : public sparse_matrix_t<unsigned,unsigned,Tdata>{
    protected:
        std::size_t nb_row;
        std::size_t nb_col;
    public:
        // Le constructeur
        indexed_sparse_matrix_t():
            sparse_matrix_t<unsigned,unsigned,Tdata>(),
            nb_row(0),nb_col(0)
        {}

        // Affecter une valeur
        // NE PLUS UTILISER LES OPERATEURS [][] pour affecter une valeur
        inline void set(const unsigned & k1,const unsigned & k2,const Tdata & d){
            (*this)[k1][k2] = d;
            if(k1 > nb_row) nb_row = k1+1;
            if(k2 > nb_col) nb_col = k2+1;
        }

        // Recuperer le nombre de ligne
        inline const std::size_t & get_nb_row() const{
            return nb_row;
        }

        // Recuperer le nombre de colonne
        inline const std::size_t & get_nb_col() const{
            return nb_col;
        }
};

// Afficher la matrice (operateur <<)
template <typename Tstream,typename Tdata>
Tstream & operator<<(Tstream & out,const indexed_sparse_matrix_t<Tdata> & m){
    const std::size_t & nb_row = m.get_nb_row();
    const std::size_t & nb_col = m.get_nb_col();
    for(std::size_t i=0;i<nb_row;++i){
        for(std::size_t j=0;j<nb_col;++j) out << m.get(i,j) << '\t';
        out << std::endl;
    }
    return out;
}

// Retourne le min de trois valeurs
template <typename Tdata>
Tdata min(const Tdata & d1,const Tdata & d2,const Tdata & d3){
    if (d1 < d2 && d1 < d3) return d1;
    if (d2 < d1 && d2 < d3) return d2;
    return d3;
}

// Calculer la somme des mins de "triplets" d'une ligne
// Tdata : un type numerique
template <typename Tdata>
Tdata compute_sum_min2(const indexed_sparse_matrix_t<Tdata> & m,unsigned i){
    const std::size_t & nb_col = m.get_nb_col();
    Tdata sum = 0;
    for(unsigned j=0;j<nb_col;j+=3){
        sum += min(m.get(i,j),m.get(i,j+1),m.get(i,j+2));
    }
    std::cout << "sum(" << i << ") = " << sum << std::endl;
    return sum;
}

int main(){
    // Initialiser la matrice
    typedef indexed_sparse_matrix_t<int> matrix_t;
    matrix_t m;
    m.set(0,2,-5);
    m.set(0,1,49);
    m.set(1,0,1);
    m.set(1,1,2);
    m.set(1,2,3);
    m.set(3,1,69);
    m.set(0,4,28);

    // Afficher la matrice
    std::cout << m << std::endl;

    const std::size_t & nb_row = m.get_nb_row();

    // Calculer head
    typedef std::list<matrix_t::row_t> head_t;
    head_t head;
    for(unsigned i=0;i<nb_row;i+=3){
        int sum_i0 = compute_sum_min2(m,i),
            sum_i1 = compute_sum_min2(m,i+1),
            sum_i2 = compute_sum_min2(m,i+2);
        int min_sum = min(sum_i0,sum_i1,sum_i2);
        if      (sum_i0 == min_sum) head.push_back(m[i]);
        else if (sum_i1 == min_sum) head.push_back(m[i+1]);
        else if (sum_i2 == min_sum) head.push_back(m[i+2]);
        else throw;
    }

    // Afficher head
    {
        head_t::const_iterator hit(head.begin()),hend(head.end());
        for(unsigned i=0;hit!=hend;++hit,++i){
            const matrix_t::row_t & row = *hit;
            matrix_t::row_t::const_iterator rit(row.begin()),rend(row.end());
            for(;rit!=rend;++rit){
                const unsigned & j = rit->first;
                const int & val = rit->second;
                std::cout << "head(" << i << ',' << j << ") = " << val << std::endl;;
            }
        }
    }

    return 0;
}

ce qui donne à l'exécution
(mando@polgara) (~) $ ./a.out
0       49      -5      0       28
1       2       3       0       0
0       0       0       0       0
0       69      0       0       0

sum(0) = -5
sum(1) = 1
sum(2) = 0
sum(3) = 0
sum(4) = 0
sum(5) = 0
head(0,1) = 49
head(0,2) = -5
head(0,4) = 28
head(1,1) = 69

On retrouve bien les termes de la ligne 0 et de la ligne 4...
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
11 mai 2007 à 10:22
Alors en fait il faut remplacer les "matrix_t" par des "indexed_sparse_matrix<int>", et les
matrix[ligne][colonne] = valeur;

par des :
matrix.set(ligne,colonne,valeur);

Du coup le :
typedef std::map<unsigned,std::map<unsigned,int> > matrix_t;

peut être supprimé.

Exemple :
bool lire_ligne(const std::string & line,indexed_sparse_matrix<int> & matrix){
...
        if(res == 2) matrix.set(ligne,colonne,valeur);
...
}

Bonne chance
0
ok merci.
j'ai testé ca marche bien , sauf que le head que je voulais calculer , je ne sais pas comment il fonctionne vraiment ! moi je cherche une valeur entiere a la fin !

sur mon exemple en haut mon head = a la somme des minimuns de triplets de lignes! et c'est ca que je veux! alors que là d'après ce que j'ai compris c'est une liste et en + quand j'execute j'ai limpression qu'il ne parcours pas toute la matrice !!

en fait pour etre plus explicite le head doit etre egale à la somme de min (s(0),s(1),s(2))+ min(s(3),s(4),s(5))+....
voila.

je remets tout le code avec son exécution ici:
j'ai corrigé un petit truc sur la fonction d'affichage de la matrice ( car la derniere colonne et ligne ne s'affichait pas , j'ai rajouté +1 à
 for(std::size_t i=0;i<nb_row+1;++i){
	for(std::size_t j=0;j<nb_col+1;++j)



donc voici le prog

#include <fstream>
#include <iostream>
#include <map>
#include <list>
#include <string>


extern "C"{
#include <stdio.h> // sscanf
#include <string.h>
}


template <typename Tkey1,typename Tkey2,typename Tdata>
class sparse_matrix_t : public std::map<Tkey1,std::map<Tkey2,Tdata> >{
public:
    typedef std::map<Tkey2,Tdata> row_t;
    typedef std::map<Tkey1,row_t> matrix_t;
    
// Recuperer une valeur
    inline Tdata get(const Tkey1 & k1,const Tkey1 & k2) const {
	typename matrix_t::const_iterator f1(this->find(k1));
	if(f1 == this->end()) return Tdata();
	const row_t & r = f1->second;
	typename row_t::const_iterator f2(r.find(k2));
	if(f2 == r.end()) return Tdata();
	return f2->second;
    }
    
};


// Une classe de matrice creuse indexée (les deux clés sont des entiers positifs)
template <typename Tdata>
class indexed_sparse_matrix_t : public sparse_matrix_t<unsigned,unsigned,Tdata>{
protected:
    std::size_t nb_row;
    std::size_t nb_col;
public:
// Le constructeur
    indexed_sparse_matrix_t():
	sparse_matrix_t<unsigned,unsigned,Tdata>(),
	nb_row(0),nb_col(0)
	{}
    
// Affecter une valeur
// NE PLUS UTILISER LES OPERATEURS [][] pour affecter une valeur
    inline void set(const unsigned & k1,const unsigned & k2,const Tdata & d){
	(*this)[k1][k2] = d;
	if(k1 > nb_row) nb_row = k1+1;
	if(k2 > nb_col) nb_col = k2+1;
    }
    
// Recuperer le nombre de ligne
    inline const std::size_t & get_nb_row() const{
	return nb_row;
    }
    
// Recuperer le nombre de colonne
    inline const std::size_t & get_nb_col() const{
	return nb_col;
    }
};

// Afficher la matrice (operateur <<)
template <typename Tstream,typename Tdata>
Tstream & operator<<(Tstream & out,const indexed_sparse_matrix_t<Tdata> & m){
    const std::size_t & nb_row = m.get_nb_row();
    const std::size_t & nb_col = m.get_nb_col();
    for(std::size_t i=0;i<nb_row+1;++i){
	for(std::size_t j=0;j<nb_col+1;++j) out << m.get(i,j) << '\t';
	out << std::endl;
    }
    return out;
}

// Retourne le min de trois valeurs
template <typename Tdata>
Tdata min(const Tdata & d1,const Tdata & d2,const Tdata & d3){
    if (d1 < d2 && d1 < d3) return d1;
    if (d2 < d1 && d2 < d3) return d2;
    return d3;
}

// Calculer la somme des mins de "triplets" d'une ligne
// Tdata : un type numerique
template <typename Tdata>
Tdata compute_sum_min2(const indexed_sparse_matrix_t<Tdata> & m,unsigned i){
    const std::size_t & nb_col = m.get_nb_col();
    Tdata sum = 0;
    for(unsigned j=0;j<nb_col+1;j+=3){
	sum += min(m.get(i,j),m.get(i,j+1),m.get(i,j+2));
    }
    std::cout << "sum(" << i << ") = " << sum << std::endl;
    return sum;
}



bool lire_ligne(const std::string & line,indexed_sparse_matrix_t<int> & matrix){
    const char *str = line.c_str();
    char *buffer = (char *)malloc(sizeof(char)*(line.size()+1));
    strcpy(buffer,str);
    unsigned ligne=0;
    unsigned colonne=0;
    int valeur;
    char *sep = "()";
    char *maillon, *brkt;

    if(sscanf(buffer," %i : ",&ligne)!=1){
        free(buffer);
        return false;
    }
    strtok_r(buffer,":", &brkt);
//  std::cout << " :  >> buffer = " << buffer << std::endl;
//  std::cout << " :  >> brkt = " << brkt << std::endl;
    for (maillon = strtok_r(brkt, sep, &brkt); maillon; maillon = strtok_r(NULL, sep, &brkt)){
	//   printf("maillon = [%s] \n", maillon);
        int res = sscanf(maillon,"%i,%d ",&colonne,&valeur);
        if(res == 2) matrix.set(ligne,colonne,valeur);
    }

    free(buffer);
    return true;
}


bool lire_fichier(const char *filename,indexed_sparse_matrix_t<int> & matrix){
    std::ifstream f(filename);
    if (f){
        std::cout << "Lecture de [" << filename << ']' << std::endl;
        std::string line;
        for(unsigned noline=1;std::getline(f,line);++noline){
            if(line.empty()) continue;
            if(!lire_ligne(line,matrix)){
                std::cerr << "Erreur : ligne invalide : ligne " << noline << ": "
                    << line << std::endl;
                return false; // on arrê la lecture
            }
        }
        return true; // lecture ok
    }
    std::cerr << "Ne peut ouvrir [" << filename << ']' << std::endl;
    return false; // le fichier n'existe pas ou ne peut êe ouvert
}



int main(){
// Initialiser la matrice
    typedef indexed_sparse_matrix_t<int> matrix_t;
    matrix_t m;
    
    const char *filename="test.txt";

    // Lire le fichier
    if(!lire_fichier(filename,m)){
        std::cerr << "Le contenu du fichier [" << filename << "] est invalide " << std::endl;
        return 1;
    }
/*
    m.set(0,2,-5);
    m.set(0,1,49);
    m.set(1,0,1);
    m.set(1,1,2);
    m.set(1,2,3);
    m.set(3,1,69);
    m.set(0,4,28);
*/  
// Afficher la matrice
    std::cout << m << std::endl;
    
    const std::size_t & nb_row = m.get_nb_row();

// Calculer head
    typedef std::list<matrix_t::row_t> head_t;
    head_t head;
    for(unsigned i=0;i<nb_row;i+=3){
	int sum_i0 = compute_sum_min2(m,i),
	    sum_i1 = compute_sum_min2(m,i+1),
	    sum_i2 = compute_sum_min2(m,i+2);
	int min_sum = min(sum_i0,sum_i1,sum_i2);
	if (sum_i0 == min_sum) head.push_back(m[i]);
	else if (sum_i1 == min_sum) head.push_back(m[i+1]);
	else if (sum_i2 == min_sum) head.push_back(m[i+2]);
	else throw;
    }
     
// Afficher head
    {
	head_t::const_iterator hit(head.begin()),hend(head.end());
	for(unsigned i=0;hit!=hend;++hit,++i){
	    const matrix_t::row_t & row = *hit;
	    matrix_t::row_t::const_iterator rit(row.begin()),rend(row.end());
	    for(;rit!=rend;++rit){
		const unsigned & j = rit->first;
		const int & val = rit->second;
			std::cout << "head(" << i << ',' << j << ") = " << val << std::endl;;
	    }
	}
    }
  
    return 0;
}


après exécution on obtient ca :

Lecture de [test.txt]
0       0       0       5       2       8       3       2       4
0       0       0       8       4       1       7       5       3
0       0       0       7       4       2       2       3       6
5       8       7       0       0       0       2       6       8
2       4       4       0       0       0       3       9       1
8       1       2       0       0       0       6       7       9
3       7       2       2       3       6       0       0       0
2       5       3       6       9       7       0       0       0
4       3       6       8       1       9       0       0       0

sum(0) = 4
sum(1) = 4
sum(2) = 4
sum(3) = 7
sum(4) = 3
sum(5) = 7
sum(6) = 4
sum(7) = 8
sum(8) = 4
head(0,1) = 0
head(0,2) = 0
head(0,3) = 5
head(0,4) = 2
head(0,5) = 8
head(0,6) = 3
head(0,7) = 2
head(0,8) = 4
head(1,0) = 2
head(1,1) = 4
head(1,2) = 4
head(1,3) = 0
head(1,5) = 0
head(1,6) = 3
head(1,7) = 9
head(1,8) = 1
head(2,0) = 3
head(2,1) = 7
head(2,2) = 2
head(2,3) = 2
head(2,4) = 3
head(2,5) = 6
head(2,7) = 0
head(2,8) = 0


donc la matrice est correcte ! les calculs de sum est juste!!
mais par contre le head pas bien compris ce qu'il fait!


merci en tt cas!
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
11 mai 2007 à 16:51
Si si il parcourt toute la matrice. En fait ton head si j'ai bien compris vaut :
int main(){
//...
    // Calculer head
    typedef std::vector<unsigned> head_t;
    head_t head;
    for(unsigned i=0;i<nb_row;i+=3){
        int sum_i0 = compute_sum_min2(m,i),   // ligne i
            sum_i1 = compute_sum_min2(m,i+1), // ligne i+1
            sum_i2 = compute_sum_min2(m,i+2); // ligne i+2
        head.push_back(sum_i0+sum_i1+sum_i1); 
    }

    for(std::size_t i=0;i<head.size();++i){
      std::cout << "head(" << i << ") = " << head[i] << std::endl;
    }
    return 0;
}

Bonne chance
0
il ya des erreurs de compilation :

> g++ projet.cpp
projet.cpp: In function `int main()':
projet.cpp:178: error: ISO C++ forbids declaration of `vector' with no type
projet.cpp:178: error: template-id `vector<unsigned int>' used as a declarator
projet.cpp:178: error: syntax error before `;' token
projet.cpp:179: error: `head_t' undeclared (first use this function)
projet.cpp:179: error: (Each undeclared identifier is reported only once for
   each function it appears in.)
projet.cpp:184: error: `head' undeclared (first use this function)


avec un autre compilateur :

> icc projet.cpp
projet.cpp(178): error: qualified name is not allowed
      typedef std::vector<unsigned> head_t;
              ^

projet.cpp(178): error: expected a ";"
      typedef std::vector<unsigned> head_t;
                         ^

projet.cpp(179): error: identifier "head_t" is undefined
      head_t head;
      ^

compilation aborted for projet.cpp (code 2)



or j'ai fait autrement et je trouve le bon résultat . mais je ne sais si c'est bien correcte!

  int head=0;
    for(unsigned i=0;i<nb_row+1;i+=3){
	int sum_i0 = compute_sum_min2(m,i),
	    sum_i1 = compute_sum_min2(m,i+1),
	    sum_i2 = compute_sum_min2(m,i+2);
	int min_sum = min(sum_i0,sum_i1,sum_i2);
//	if (sum_i0 == min_sum) head.push_back(m[i]);
//	else if (sum_i1 == min_sum) head.push_back(m[i+1]);
//	else if (sum_i2 == min_sum) head.push_back(m[i+2]);
//	else throw;
	head = head +min_sum;
	
	}*/
    //   std::cout<<head ;
0
int head=0;
for(unsigned i=0;i<nb_row+1;i+=3){ // ICI J'AI MI +1 au nb_col
int sum_i0 = compute_sum_min2(m,i),
sum_i1 = compute_sum_min2(m,i+1),
sum_i2 = compute_sum_min2(m,i+2);
int min_sum = min(sum_i0,sum_i1,sum_i2);

head = head +min_sum;

}
std::cout<<head ;

donc STP di moi si c'est bon ! mercii
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
11 mai 2007 à 18:36
#include <vector>

Tout simplement
0
ok merci ca marche!
mais je crois que ca ne répond pas a la question! puisque on voulais calculer head de tel sorte qu'il soit egale a la somme des min de 3" triplet " de lignes ie :

head = min (sum_io(0),sum_i1(1),sum_i2(2)) + min ( sum_i0(3),sum_i1(4),sum_i2(5))+....

et en plus mon head doit etre un entier alors que l'a c'un vecteur! en fait ce que je ne comprend pas , c'est la fonction "push_back"
et en plus ici
  head.push_back(sum_i0+sum_i1+sum_i1);

on ajoute les lignes entre elle.

donc je ne compren pa trè bien. merci.
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
11 mai 2007 à 20:55
En fait c'est moi qui ne comprends pas ce que tu veux calculer. Je pense que si tu as compris le programme tu es capable de l'adapter. En tout cas moi je capte rien à l'énoncé ^^
0
merci bien en tout cas! j'ai reussi à l'adapter! et ca marche!
encore un grand merci.++
0
bonjour !!
comment faire pour developper la classe matrice creuse qui permet de representer les matrices creuses???.La classe developpée supportera une interface de visualisation ,de saisie et de mise a jour de la matrice ?????????????
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
29 nov. 2007 à 09:05
myriam idéalement il faudrait ouvrir un nouveau post puisque c'est un nouveau problème. L'idée c'est d'utiliser une map de map :
#include <map>
#include <iostream>

template <typename T>
class sparse_matrix_t : public std::map<unsigned,std::map<unsigned,T> >{
     public:
            sparse_matrix_t(){}

            // Accéder à la valeur m(k1,k2)
            inline const T & get_value(const unsigned & k1,const unsigned & k2) const{
                typename std::map<unsigned,std::map<unsigned,T> >::const_iterator
                    data_k1_it = this->find(k1);
                if (data_k1_it == this->end()) throw;
                const std::map<unsigned,T> & data_k1 = data_k1_it->second;
                typename std::map<unsigned,T>::const_iterator
                    data_k1_k2_it = data_k1.find(k2);
                if (data_k1_k2_it == data_k1.end()) throw;
                return data_k1_k2_it->second;
            }

            // (Re)définir la valeur m(k1,k2)
            inline void set(const unsigned & k1,const unsigned & k2,const T & val){
                (*this)[k1][k2] = val;
            }
};

int main(){
  sparse_matrix_t<int> m;
  m.set(1,2,45);
  std::cout << "m(1,2) = " << m.get_value(1,2) << std::endl;
  return 0;
}

Bonne chance
0
Je vous remercie.
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
30 nov. 2007 à 11:05
Pas de soucis, bonne continuation !
0
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
3 janv. 2008 à 21:43
Ben en fait ce n'est pas vraiment à nous de faire tes exercices à ta place, mais par contre on peut t'aider si tu bloques sur certains points. Merci d'ouvrir alors un nouveau post, expliquant ton problème, où tu en es, et ce qui te bloque, car ce post est résolu.

Bonne continuation
0