Séance d'exercices 11, Programmation I
Sciences et Technologies du Vivant, Semestre 1

Exercice 1 - Fonctions d'algèbre linéaire

Dans cet exercice, vous allez mettre en \oeuvre les fonctions d'algèbre linéaire que vous avez vues en cours.

  1. Commencez par définir une structure Matrice
    struct Matrice {
      float *tab;
      int nl, nc;
    };
    

    Ajoutez ensuite le code pour les fonctions get et set permettant d'accéder aux éléments du tableau. Comme suggéré dans le cours, vérifiez que la ligne et la colonne auxquelles on désire accéder sont bien valides. Ajoutez également les fonctions alloue_matrice et affiche.

    Toutes ces fonctions ont été vues en cours, et leur implémentation ne devrait donc pas poser de problèmes.

  2. Rédigez le code d'une fonction copie, dont le but est de copier le contenu d'une matrice dans une autre. La fonction prendra deux arguments: un pointeur sur la matrice source et un autre sur la matrice destination. On suppose que la matrice destination a déjà été allouée. La fonction prendra soin de vérifier que les deux matrices ont bien la même taille, avant d'effectuer la copie.

  3. Ecrivez deux fonctions intitulées set_id et set_0 permettant d'initialiser une matrice à la matrice identité et à la matrice nulle, respectivement.

    Les en-têtes de ces fonctions devront être:

    bool set_id(Matrice *mat);
    void set_0(Matrice *mat);
    

    La fonction set_id retournera false si la matrice passée en paramètre n'est pas carrée, et true si l'opération s'est bien passée.

  4. Implémentez une fonction init permettant d'initialiser une matrice. Vous allez écrire une fonction différente pour chaque type de matrice que vous voudrez initialiser. Par exemple, pour initialiser une matrice 2$\times$2, vous devrez écrire la fonction
    void init(Matrice *matrice, float c1, float c2, float c3, float c4)
    

    alors que pour initialiser une matrice 2$\times$3, il faudra utiliser

    void init(Matrice *matrice, float c1, float c2, float c3, float c4, 
              float c5, float c6)
    

    car elle contient 6 coefficients. Cette dernière fonction peut, par ailleurs, autant servir à initialiser une matrice 3$\times$2 que 2$\times$3. Soyez donc bien attentifs lorsque vous l'implémentez. On supposera qu'une matrice à 6 coefficients n'a pas la forme 1$\times$6 ou 6$\times$1, car la structure Vecteur s'occupera de ces cas-là.

  5. Dans votre fonction main, déclarez deux matrices M1 et M2 dans main et initialisez-les comme suit (sans oublier de les allouer auparavant):

    \begin{displaymath}
M1 \leftarrow \left(\begin{array}{c c c}
1 & 3 & -4 \\
-5 & 2 & 0 \\
\end{array} \right)
\end{displaymath}

    et

    \begin{displaymath}
M2 \leftarrow \left(\begin{array}{c c c}
6 & 2 & -1 \\
1 & -2 & 5 \\
\end{array} \right).
\end{displaymath}

    Ecrivez une nouvelle fonction

    void add_mat(Matrice *m1, Matrice *m2, Matrice *res)
    

    qui additionne les matrices m1 et m2 et met le résultat dans res (res est censée avoir été allouée).

    Testez votre fonction sur M1 et M2 et affichez le résultat à l'aide de affiche. Vérifiez que celui-ci est bien égal à

    \begin{displaymath}
\left(\begin{array}{c c c}
7 & 5 & -5 \\
-4 & 0 & 5 \\
\end{array} \right).
\end{displaymath}

  6. Ecrivez maintenant la structure Vecteur
    struct Vecteur {
      float *tab;
      int n;
    };
    

    ainsi que les fonctions relatives: get, set, affiche et alloue_vecteur. Ces fonctions ont également été vues en cours. Remarquez que 2 fonctions peuvent avoir le même nom, pour autant qu'elles aient des paramètres différents.

    Ajoutez aussi une fonction

    void init(Vecteur *vecteur, float c1, float c2, float c3, float c4)
    

    pour initialiser un vecteur 4$\times$1.

  7. Dans main, déclarez et initialisez les deux vecteurs suivants:

    \begin{displaymath}
V1 \leftarrow \left(\begin{array}{c}
2  5  3  4 \\
\end{array} \right)
\end{displaymath}

    et

    \begin{displaymath}
V2 \leftarrow \left(\begin{array}{c}
3  2  -3  1 \\
\end{array} \right).
\end{displaymath}

    Ajoutez la fonction norm_vect qui renvoie la norme d'un vecteur, et testez-la sur V1 et V2. Vous devez trouver à peu près 7.34 pour V1 et 4.79 pour V2.

    Ajoutez également la fonction produit_scalaire qui renvoie le produit scalaire de deux vecteurs, et testez-la sur V1 et V2. Vous devez trouver 11.

  8. Ajoutez la fonction
    void init3x4(Matrice *matrice, 
                 float c1, float c2,  float c3,  float c4, 
                 float c5, float c6,  float c7,  float c8,
                 float c9, float c10, float c11, float c12)
    

    permettant d'initialiser une matrice 3$\times$4.

  9. Déclarez et initialisez les deux matrices suivantes:

    \begin{displaymath}
P1 \leftarrow \left(\begin{array}{c c c}
2 & 1 & -3 \\
5 & 1 & 5 \\
3 & 2 & 4 \\
\end{array} \right)
\end{displaymath}

    et

    \begin{displaymath}
P2 \leftarrow \left(\begin{array}{c c c c}
3 & -1 & 3 & 1 \\
2 & 3 & 5 & 2 \\
-3 & 2 & -4 & 3 \\
\end{array} \right)
\end{displaymath}

    Ecrivez la fonction trace et testez-la sur P1. Vous devez trouver 7.

  10. Ajoutez la fonction mult qui multiplie une matrice par un vecteur, et utilisez-la pour calculer le produit de P2 et V1. Vous devez trouver:

    \begin{displaymath}
\left(\begin{array}{c}
14  42  4 \\
\end{array} \right)
\end{displaymath}

  11. Ajoutez la fonction mult qui multiplie deux matrices. Utilisez-la pour calculer le produit de P1 et P2 et mettre le résultat dans une nouvelle variable P3. Vous devez trouver:

    \begin{displaymath}
\left(\begin{array}{c c c c}
17 & -5 & 23 & -5 \\
2 & 8 & 0 & 22 \\
1 & 11 & 3 & 19 \\
\end{array} \right)
\end{displaymath}

  12. Ajoutez la fonction transpose_mat qui permet de transposer une matrice. Utilisez-la pour affecter transpP1 à la transposée de P1, et transpP2 à la transposée de P2.

  13. Ecrivez une nouvelle fonction intitulée libere_matrice permettant de désallouer la mémoire d'une structure Matrice. La fonction recevra un pointeur sur la structure Matrice en paramètre. Elle désallouera toute la mémoire ayant été réservée par la fonction alloue_matrice.

  14. Ajoutez des appels à libere_matrice dans le corps du programme, afin de libérer correctement toute la mémoire qui a été allouée.

Exercice 2 - Fonctions d'algèbre linéaire supplémentaires ($\dag $)

Dans cet exercice, vous allez continuer l'exercice précédent en ajoutant quelques nouvelles fonctions pour les structures Matrice et Vecteur.

  1. Ajoutez une fonction decale_a_gauche qui décale les colonnes d'une matrice vers la gauche. La colonne de gauche devra être déplacée sur la colonne de droite. Par exemple, si on applique cette fonction à P2, on obtient:

    \begin{displaymath}
\left(\begin{array}{c c c c}
-1 & 3 & 1 & 3 \\
3 & 5 & 2 & 2 \\
2 & -4 & 3 & -3 \\
\end{array} \right)
\end{displaymath}

    Ecrivez également la fonction decale_a_droite.

  2. Ecrivez une fonction qui tourne les éléments placés sur le bord d'une matrice dans le sens des aiguilles d'une montre:

    Par exemple, appliquée à la matrice P2 qui contient

    \begin{displaymath}
\left(\begin{array}{c c c c}
3 & -1 & 3 & 1 \\
2 & 3 & 5 & 2 \\
-3 & 2 & -4 & 3 \\
\end{array} \right)
\end{displaymath}

    cette fonction donnera

    \begin{displaymath}
\left(\begin{array}{c c c c}
2 & 3 & -1 & 3 \\
-3 & 3 & 5 & 1 \\
2 & -4 & 3 & 2 \\
\end{array} \right)
\end{displaymath}

  3. Ecrivez une fonction puissance_mat qui élève une matrice carrée à une puissance entière passée en paramètre.

    Par exemple, P1 élevée à la puissance 4 donne:

    \begin{displaymath}
\left(\begin{array}{c c c}
-454 & -217 & -251 \\
760 & 296 & -60 \\
866 & 345 & 55 \\
\end{array} \right)
\end{displaymath}


Retour