Corrigé de la séance d'exercices 11, Programmation I
Sciences et Technologies du Vivant, Semestre 1

Exercices 1 et 2 - Fonctions d'algèbre linéaire

#include <iostream>
#include <math.h>

using namespace std;


// ******* Structures *******

struct Matrice {
  float *tab;
  int nl, nc;
};

struct Vecteur {
  float *tab;
  int n;
};


// ******* Fonctions pour Matrice *******

float get(Matrice *mat, int ligne, int col) {
  if (ligne >= 0 && ligne < mat->nl && col >= 0 && col < mat->nc)
    return mat->tab[ligne * mat->nc + col];
  else {
    cout << "Erreur [get]: indice en dehors des bornes!" << endl;
    cout << "Matrice: " << mat->nc << " colonnes, " << mat->nl << " lignes." << endl;
    cout << "Requete: ligne " << ligne << ", colonne " << col << endl;
  }
  return 0;
}

void set(Matrice *mat, int ligne, int col, float val) {
  if (ligne >= 0 && ligne < mat->nl && col >= 0 && col < mat->nc)
    mat->tab[ligne * mat->nc + col] = val;
  else {
    cout << "Erreur [set]: indice en dehors des bornes!" << endl;
    cout << "Matrice: " << mat->nc << " colonnes, " << mat->nl << " lignes." << endl;
    cout << "Requete: ligne " << ligne << ", colonne " << col << endl;
  }
}

Matrice *alloue_matrice(int nl, int nc) {
  Matrice *res = new Matrice;

  res->nl = nl;
  res->nc = nc;
  res->tab = new float[nc * nl];

  return res;
}

void libere_matrice(Matrice *mat) {
  delete[] mat->tab;
  delete mat;
}

void affiche(Matrice *mat) {
  for (int i=0; i<mat->nl; i++) {
    for (int j=0; j<mat->nc; j++)
      cout << get(mat, i, j) << " ";
    cout << endl;
  }
}

bool set_id(Matrice *mat) {
  if (mat->nc == mat->nl) {
    for (int i=0; i<mat->nl; i++)
      for (int j=0; j<mat->nc; j++)
        if (i == j)
          set(mat, i, j, 1);
        else
          set(mat, i, j, 0);
    return true;
  }
  else {
    cout << "Erreur [set_id]: matrice non carree." << endl;
    return false;
  }
}

void set_0(Matrice *mat) {
  for (int i=0; i<mat->nl; i++)
    for (int j=0; j<mat->nc; j++)
      set(mat, i, j, 0);
}

// pour matrices a 6 coefficients
void init(Matrice *mat, float c1, float c2, float c3, float c4, float c5, 
          float c6) {
  if ((mat->nc == 3 && mat->nl == 2) || (mat->nc == 2 && mat->nl ==3)) {
    mat->tab[0] = c1;
    mat->tab[1] = c2;
    mat->tab[2] = c3;
    mat->tab[3] = c4;
    mat->tab[4] = c5;
    mat->tab[5] = c6;
  }
  else
    cout << "Erreur [init]: matrice de taille incorrecte." << endl;
}

// pour matrices a 9 coefficients
void init(Matrice *mat, float c1, float c2, float c3, float c4, float c5, 
          float c6, float c7, float c8, float c9) {
  if (mat->nc == 3 && mat->nl == 3) {
    mat->tab[0] = c1;
    mat->tab[1] = c2;
    mat->tab[2] = c3;
    mat->tab[3] = c4;
    mat->tab[4] = c5;
    mat->tab[5] = c6;
    mat->tab[6] = c7;
    mat->tab[7] = c8;
    mat->tab[8] = c9;
  }
  else
    cout << "Erreur [init]: matrice de taille incorrecte." << endl;
}

// pour matrices a 12 coefficients
void init(Matrice *mat, float c1, float c2, float c3, float c4, float c5, 
          float c6, float c7, float c8, float c9, float c10, float c11, float c12) {
  if ((mat->nc == 2 && mat->nl == 6) || (mat->nc == 3 && mat->nl == 4) ||
      (mat->nc == 4 && mat->nl == 3) || (mat->nc == 6 && mat->nl == 2)) {
    mat->tab[0] = c1;
    mat->tab[1] = c2;
    mat->tab[2] = c3;
    mat->tab[3] = c4;
    mat->tab[4] = c5;
    mat->tab[5] = c6;
    mat->tab[6] = c7;
    mat->tab[7] = c8;
    mat->tab[8] = c9;
    mat->tab[9] = c10;
    mat->tab[10] = c11;
    mat->tab[11] = c12;
  }
  else
    cout << "Erreur [init]: matrice de taille incorrecte." << endl;
}

void copie(Matrice *mat, Matrice *res) {
  if (mat->nl == res->nl && mat->nc == res->nc)
    for (int i=0; i<mat->nl; i++)
      for (int j=0; j<mat->nc; j++)
        set(res, i, j, get(mat, i, j));
  else
    cout << "Erreur [copie]: la taille des matrices ne correspond pas." << endl;
}

void add_mat(Matrice *m1, Matrice *m2, Matrice *res) {
  if (m1->nc == m2->nc && m1->nl == m2->nl && res->nc == m1->nc
      && res->nl == m1->nl)
    for (int i=0; i<m1->nl; i++)
      for (int j=0; j<m1->nc; j++)
        set(res, i, j, get(m1, i, j) + get(m2, i, j));
  else
    cout << "Erreur [add_mat]: les matrices n'ont pas la meme taille." << endl;
}

float trace(Matrice *mat) {
  float tr = 0;
  if (mat->nl == mat->nc)
    for (int i=0; i<mat->nl; i++)
      tr += get(mat, i, i);
  else
    cout << "Erreur [trace]: matrice non carree." << endl;

  return tr;
}

void mult(Matrice *m1, Matrice *m2, Matrice *res) {
  if (m1->nc == m2->nl && res->nl == m1->nl && res->nc == m2->nc)
    for (int i=0; i<m1->nl; i++)
      for (int j=0; j<m2->nc; j++) {
        res->tab[i * res->nc + j] = 0;
        for (int k=0; k<m1->nc; k++)
          res->tab[i * res->nc + j] += get(m1, i,  k) * get(m2, k, j);
      }
  else
    cout << "Erreur [mult_mat]: la taille des matrices ne correspondent pas." << endl;
}

void transpose_mat(Matrice *mat, Matrice *res) {
  if (mat->nc == res->nl && mat->nl == res->nc)
    for (int i=0; i<res->nl; i++)
      for (int j=0; j<res->nc; j++)
        set(res, i, j, get(mat, j, i));
  else
    cout << "Erreur [transpose_mat]: la taille des matrices ne correspondent pas." << endl;
}


// ******* Fonctions pour Vecteur *******

float get(Vecteur *vec, int n) {
  if (n >= 0 && n < vec->n)
    return vec->tab[n];
  else {
    cout << "Erreur [get]: indice en dehors des bornes!" << endl;
    cout << "Vecteur: " << vec->n << " elements" << endl;
    cout << "Requete: element " << n << endl;
  }
  return 0;
}

void set(Vecteur *vec, int n, float val) {
  if (n >= 0 && n < vec->n)
    vec->tab[n] = val;
  else {
    cout << "Erreur [set]: indice en dehors des bornes!" << endl;
    cout << "Vecteur: " << vec->n << " elements" << endl;
    cout << "Requete: element " << n << endl;
  }
}

Vecteur *alloue_vecteur(int n) {
  Vecteur *res = new Vecteur;

  res->n = n;
  res->tab = new float[n];

  return res;
}

void libere_vecteur(Vecteur *vec) {
  delete[] vec->tab;
  delete vec;
}

void affiche(Vecteur *vec) {
  for (int i=0; i<vec->n; i++)
    cout << get(vec, i) << endl;
}

void init(Vecteur *vec, float c1, float c2, float c3, float c4) {
  if (vec->n == 4) {
    vec->tab[0] = c1;
    vec->tab[1] = c2;
    vec->tab[2] = c3;
    vec->tab[3] = c4;
  }
  else
    cout << "Erreur [init]: vecteur de taille incorrecte." << endl;
}

float norm_vect(Vecteur *vec) {
  float somme = 0;
  for (int i=0; i<vec->n; i++)
    somme += get(vec, i) * get(vec, i);
  return sqrt(somme);
}

float produit_scalaire(Vecteur *v1, Vecteur *v2) {
  float produit = 0;

  if (v1->n != v2->n)
    cout << "Erreur [produit_scalaire]: les vecteurs n'ont pas la meme taille." << endl;
  else {
    for (int i=0; i<v1->n; i++)
      produit += v1->tab[i] * v2->tab[i];
  }

  return produit;
}

void mult(Matrice *mat, Vecteur *vec, Vecteur *res) {
  if (vec->n == mat->nc && res->n == mat->nl)
    for (int i=0; i<mat->nl; i++) {
      res->tab[i] = 0;
      for (int j=0; j<mat->nc; j++)
        res->tab[i] += get(mat, i, j) * get(vec, j);
    }
  else
    cout << "Erreur [mult_mat_vec]: la taille des vecteurs et de la matrice ne correspondent pas." << endl;
}


// ******* Fonctions de l'exercice 3 *******

void decale_a_gauche(Matrice *mat, Matrice *res) {
  if (mat->nl == res->nl && mat->nc == res->nc) {
    for (int i=0; i<mat->nl; i++)
      for (int j=0; j<mat->nc; j++)
        set(res, i, (j+mat->nc-1) % mat->nc, get(mat, i, j));
  }
  else
    cout << "Erreur [decale_a_gauche]: la taille des matrices ne correspond pas." << endl;
}

void decale_a_droite(Matrice *mat, Matrice *res) {
  if (mat->nl == res->nl && mat->nc == res->nc) {
    for (int i=0; i<mat->nl; i++)
      for (int j=0; j<mat->nc; j++)
        set(res, i, (j+1) % mat->nc, get(mat, i, j));
  }
  else
    cout << "Erreur [decale_a_droite]: la taille des matrices ne correspond pas." << endl;
}

void tourne(Matrice *mat, Matrice *res) {
  if (mat->nl == res->nl && mat->nc == res->nc) {
    // ligne superieure
    for (int i=1; i<mat->nc; i++)
      set(res, 0, i, get(mat, 0, i-1));
    // ligne inferieure
    for (int i=0; i<mat->nc-1; i++)
      set(res, mat->nl-1, i, get(mat, mat->nl-1, i+1));
    // ligne de gauche
    for (int i=0; i<mat->nl-1; i++)
      set(res, i, 0, get(mat, i+1, 0));
    // ligne de droite
    for (int i=1; i<mat->nl; i++)
      set(res, i, mat->nc-1, get(mat, i-1, mat->nc-1));
    
    // autres lignes
    for (int i=1; i<mat->nl-1; i++)
      for (int j=1; j<mat->nc-1; j++)
        set(res, i, j, get(mat, i, j));
  }
  else
    cout << "Erreur [tourne]: la taille des matrices ne correspond pas." << endl;
}

void puissance_mat(Matrice *mat, int exposant, Matrice *res) {
  Matrice *tmp = alloue_matrice(mat->nl, mat->nl);
  set_id(res);
  if (mat->nc == mat->nl && res->nc == mat->nc && res->nl == mat->nl) {
    for (int i=0; i<exposant; i++) {
      mult(mat, res, tmp);
      copie(tmp, res);
    }
  }
  else
    cout << "Erreur [puissance_mat]: la taille des matrices ne correspond pas." << endl;

  libere_matrice(tmp);
}


int main(int argc, char **argv) {
  Matrice *M1 = alloue_matrice(2, 3);
  Matrice *M2 = alloue_matrice(2, 3);

  init(M1, 1, 3, -4, -5, 2, 0);
  init(M2, 6, 2, -1, 1, -2, 5);

  cout << "M1:" << endl;
  affiche(M1);
  cout << endl << "M2:" << endl;
  affiche(M2);

  Matrice *M3 = alloue_matrice(2, 3);
  add_mat(M1, M2, M3);

  cout << endl << "M3 = M1 + M2:" << endl;
  affiche(M3);
  cout << endl;

  libere_matrice(M1);
  libere_matrice(M2);
  libere_matrice(M3);

  Vecteur *V1 = alloue_vecteur(4);
  Vecteur *V2 = alloue_vecteur(4);

  init(V1, 2, 5, 3, 4);
  init(V2, 3, 2, -3, 1);

  cout << "V1:" << endl;
  affiche(V1);
  cout << endl << "V2:" << endl;
  affiche(V2);
  cout << endl << "Norme de V1: " << norm_vect(V1) << endl;
  cout << "Norme de V2: " << norm_vect(V2) << endl << endl;

  cout << "Produit scalaire <V1, V2> = " << produit_scalaire(V1, V2) << endl;

  Matrice *P1 = alloue_matrice(3, 3);
  Matrice *P2 = alloue_matrice(3, 4);
  
  init(P1, 2, 1, -3, 5, 1, 5, 3, 2, 4);
  init(P2, 3, -1, 3, 1, 2, 3, 5, 2, -3, 2, -4, 3);

  cout << endl << "P1:" << endl;
  affiche(P1);
  cout << endl << "P2:" << endl;
  affiche(P2);

  cout << endl << "Trace de P1: " << trace(P1) << endl;

  Vecteur *V3 = alloue_vecteur(3);

  mult(P2, V1, V3);

  cout << endl << "P2 * V1:" << endl;
  affiche(V3);
  cout << endl;

  libere_vecteur(V1);
  libere_vecteur(V2);
  libere_vecteur(V3);

  Matrice *P3 = alloue_matrice(3, 4);

  mult(P1, P2, P3);

  cout << endl << "P1 * P2:" << endl;
  affiche(P3);
  cout << endl;

  Matrice *transpP1 = alloue_matrice(3, 3);
  Matrice *transpP2 = alloue_matrice(4, 3);

  transpose_mat(P1, transpP1);
  transpose_mat(P2, transpP2);
  
  cout << "P1 transposee:" << endl;
  affiche(transpP1);
  cout << endl << "P2 transposee:" << endl;
  affiche(transpP2);
  cout << endl;

  libere_matrice(transpP1);
  libere_matrice(transpP2);

  cout << "Exercice 2:" << endl;

  decale_a_gauche(P2, P3);

  cout << endl << "P2 decalee a gauche:" << endl;
  affiche(P3);

  tourne(P2, P3);

  cout << endl << "P2 tournee:" << endl;
  affiche(P3);

  Matrice *P4 = alloue_matrice(3, 3);
  puissance_mat(P1, 4, P4);

  cout << endl << "P1 a la puissance 4:" << endl;
  affiche(P4);

  libere_matrice(P1);
  libere_matrice(P2);
  libere_matrice(P3);
  libere_matrice(P4);

  return 0;
}


Retour