• # Lisibilité et produit de matrices

    Posté par . En réponse à la dépêche OCaml 3.10.0 est sorti. Évalué à 6.

    • Pour répondre à quelques objections sur la lisibilité, il me semble que tout langage permet d'écrire des choses illisibles (à partir du moment où il est Turing complet du moins). Un bon langage de programmation à mon sens est un langage qui permet d'écrire lisiblement. Dans pas mal de situations, Caml permet d'écrire lisiblement là où ni C ni Java ne le permettent (et la réciproque est plutôt rare).
    • Un code caml qui implante le produit de matrice peut être tout à fait lisible en fonctionnel et bien plus lisible que les versions impératives : deux fonctions auxiliaires (sigma et init_matrix) d'une ligne et une ligne pour le produit en lui même. C'est très lisible à partir du moment où on sait que "(fun i j -> expr)" désigne la fonction qui à i et j associe "expr".
    • Comme je ne suis pas doué, j'ai évidemment fait beaucoup d'erreurs en écrivant le code ci-dessous. Le compilo caml les a toutes corrigées, sauf une dans la fonction sigma qui conduisait à une boucle infinie systématiquement. Correction du bug -> tout baigne. C'est pas en C ni en Java qu'on aurait le même confort.
    • Cas des matrices de taille n fixée :
      (* Fonction d'intérêt général *)
      (* Calcule (f i) + (f (i+1) + ... + (f j) *)
      let rec sigma i j f = if j < i then 0. else (f i) +. sigma (i+1) j f;;
      (* taille des matrices *)
      let n = ...
      (* Construit la matrice des (f i j) *)
      let init_matrix f = Array.init n (fun i -> Array.init n (fun j -> f i j));;
      (* somme de matrices, juste pour s'amuser *)
      let sum p1 p2 = init_matrix (fun i j -> p1.(i).(j) +. p2.(i).(j));;
      ;;
      let prod p1 p2 =
       init_matrix (fun i j -> sigma 0 (n-1) (fun k -> p1.(i).(k) *. p2.(k).(j)))
      ;;
      
    • Cas des matrices de taille dynamique :
      (* Calcule (f i) + (f (i+1) + ... + (f j) *)
      let rec sigma i j f = if j < i then 0. else (f i) +. sigma (i+1) j f;;
      (* construit la matrice des (f i j), 0<=i<n, 0<=j<m *)
      let init_matrix n m f =
       Array.init n (fun i -> Array.init m (fun j -> f i j))
      ;;
      (* dimensions d'une matrice *)
      let dim_matrix p =
       let n = Array.length p in
       assert (n<>0);
       let m = Array.length p.(0) in
       (n,m)
      ;;
      (* somme de matrices, juste pour s'amuser *)
      let sum p1 p2 =
       let (n1,m1) = dim_matrix p1
       and (n2,m2) = dim_matrix p2 in
       assert (n1 = n2 && m1 = m2);
       init_matrix n1 m1 (fun i j -> p1.(i).(j) +. p2.(i).(j))
      ;;
      let prod p1 p2 =
       let (n1,m1) = dim_matrix p1
       and (n2,m2) = dim_matrix p2 in
       assert (m1 = n2);
       let c i j = sigma 0 (m1-1) (fun k -> p1.(i).(k) *. p2.(k).(j)) in
       init_matrix n1 m2 c
      ;;