29/03/17 1 III) opérations d'ordre sup sur les séquences Typologie des fonctions sur une séquence [e1 ; ... ; en] : 1) fonctions dont le résultat est scalaire : a) prédicats (scalaire = booléen) : - existence d'un ei satisfaisant une propriété (∃) - tous les ei satisfont une propriété (∀) b) opérations (scalaire = autre) : - somme des f(ei) (∑) - produit des f(ei) (∏) 2) fonctions dont le résultat est une séquence : a) application d'une fonction sur chaque ei b) sélection des ei vérifiant une propriété inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 2 III) opérations d'ordre sup sur les séq — prédicats 1) Fonctions dont le résultat est scalaire a) Prédicats SPÉC Profil existence d'un élément satisfaisant une propriété existe : (α IB) séq(α) IB Sémant. (existe p s) = vrai ssi ∃ ei ∈ s / p(ei) = vrai Ex. (existe (e e mod 3 = 0) [-2 ; 1 ; 6]) = vrai (existe (e 'a' < e < 'z') ['C' ;'A' ;'M' ;'L']) = faux inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 3 III) opérations d'ordre sup sur les séq — prédicats existe : (α IB) séq(α) IB existence d'un élément satisfaisant une propriété RÉAL Algo 1 application modèle d'analyse Mséq(Elt) sur (existe p) (voir partie 2) …/... tableau Algo 2 NB spécialisation de fold, étudiée dans la suite existe défini dans la librairie standard : List.exists inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 4 III) opérations d'ordre sup sur les séq — prédicats List.exists : ('a → bool) → 'a list → bool Une spécialisation de List.exists : prédicat d'appartenance app_seq : Exemple : ( app_seq 2 [-3;2;5] ) = vrai let app_séq (x:'a) : 'a list -> bool = (* application partielle de existe : *) (List.exists (function e -> e = x)) NB app_seq définie dans la librairie standard : List.mem inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 5 III) opérations d'ordre sup sur les séq — prédicats SPÉC Profil tous les éléments satisfont une propriété pour_tous : (α IB) séq(α) IB Sémant. (pour_tous p s) = vrai ssi ∀ ei ∈ s, p(ei) = vrai Ex. (pour_tous (e e mod 3 = 0) [-3 ; 0 ; 5]) = faux (pour_tous (e 'a' < e ∧ e < 'z') ['k';'l';'f';'e';'z';'f']) = vrai inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 6 III) opérations d'ordre sup sur les séq — prédicats pour_tous : (α IB) séq(α) IB RÉAL Algo 1 tous les éléments satisfont une propriété application de Mséq(a) sur (pour_tous p) (cf partie 2) …/... (tableau) Algo 2 spécialisation de fold (voir suite) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 7 III) opérations d'ordre sup sur les séq — prédicats RÉAL Algo 3 SPÉC Profil tous les éléments satisfont une propriété (suite) ∀ ⇔ ¬∃ ¬ est la négation négation d'un prédicat unaire neg : (α IB) (α IB) Sémant. (neg p) est la négation de p, c-a-d vaut vrai quand p vaut faux Ex. (neg (x x = 0)) = (x x ≠ 0) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 8 III) opérations d'ordre sup sur les séq — prédicats neg : (α IB) (α IB) (neg p) est la négation de p, c-a-d vaut vrai quand p vaut faux RÉAL Algo. négation d'un prédicat unaire utilisation de not : bool -> bool Implémentation : let neg (p:'a -> bool) : 'a -> bool = function x -> not (p x) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 9 III) opérations d'ordre sup sur les séq — prédicats # neg (function x -> x=0) ;; - : 'a -> bool = <fun> 1≠0? # (neg (function x -> x=0)) 1 ;; - : bool = true 0≠0? # (neg (function x -> x=0)) 0 ;; - : bool = false inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 10 III) opérations d'ordre sup sur les séq — prédicats pour_tous : (αIB) séq(α) IB (pour_tous p s) = vrai ssi ∀ ei ∈ s, p(ei) = vrai tous les éléments satisfont une propriété RÉAL Algo 3 ∀ ei ∈ s, p(ei) ⇔ ¬ ∃ ei ∈ s, ¬ p(ei) ⇔ ¬ ∃ ei ∈ s, (¬ p) (ei) Implémentation 3 : let pour_tous (p:'a -> bool) : 'a list -> bool = function s -> not (List.exists (neg p) s) NB pour_tous défini dans la librairie standard : List.for_all inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 11 IV) opérations d'ordre sup sur les séquences Typologie des fonctions sur une séquence [e1 ; ... ; en] : 1) Fonctions dont le résultat est scalaire : a) Prédicats : - existence d'un ei satisfaisant une propriété (∃) - tous les ei satisfont une propriété (∀) b) Opérations : - somme des f(ei) (∑) - produit des f(ei) (∏) - opération sur les f(ei) () 2) Fonctions dont le résultat est une séquence : a) Application d'une fonction sur chaque ei b) Sélection des ei vérifiant une propriété inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 12 IV) opérations d'ordre sup sur les séq — opérations 1) Fonctions dont le résultat est scalaire b) Opérations opération sur les éléments d'une séquence non vide SPÉC Profil oméga : (ßßß) (αß) séq*(α) ß Sémant. Soit opé une opération ∈ ßßß (notée de manière infixe) notation infixée f une fonction ∈ αß (oméga opé f [e1 ; ... ; en]) = f(e1) opé ... opé f(en) = Ex. n i =1 f ei (oméga (+) (x x2) [-2;1;3]) = 4 + 1 + 9 = 14 inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 13 IV) opérations d'ordre sup sur les séq — opérations RÉAL Algo 1 application modèle d'analyse Mséq*(α) sur (oméga opé f) n et, pour n ≥ 2, i 1 n f ei = f e1 opé = i 2 f ei = (1) (oméga opé f [e]) = f(e) (2) soit fin ∈ séq(α1)* (oméga opé f pr::fin) = f(pr) opé (oméga opé f fin) Implémentation 1 : analyse par cas par filtrage inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 14 IV) opérations d'ordre sup sur les séq — opérations RÉAL Algo 2 spécialisation de fold, étudiée dans la suite inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 15 IV) opérations d'ordre sup sur les séq — opérations oméga : (ßßß) (αß) séq*(α) ß (oméga opé f [e1 ; ... ; en]) = f(e1) opé ... opé f(en) Utilisation : ● directe : somme des carrés des éléments d'une séquence : # (oméga ( + ) (fun e -> e*e) [-2;1;3]) ;; - : int = 14 produit : # (oméga ( * ) - : int = -6 (fun e -> e) inf121 : algorithmique et programmation fonctionnelle [-2;1;3]) ;; 3ème partie : ordre supérieur 29/03/17 16 IV) opérations d'ordre sup sur les séq — opérations oméga : (ßßß) (αß) séq*(α) ß (oméga opé f [e1 ; ... ; en]) = f(e1) opé ... opé f(en) longueur d'une séquence : # (oméga ( + ) (fun _ -> 1) [-2;1;3]) ;; - : int = 3 NB définie dans la librairie standard : List.length inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 17 IV) opérations d'ordre sup sur les séq — opérations oméga : (ßßß) (αß) séq*(α) ß (oméga opé f [e1 ; ... ; en]) = f(e1) opé ... opé f(en) Utilisation : ● indirecte : Implémentation de ∑ (sur les séquences) : let sigma (f:'a->int) (s:'a list) : int = if s = [] then 0 else (oméga (+) f s) Utilisation de sigma : let sommeCarrés : int list -> int = (sigma (function e -> e*e)) # sommeCarrés [-2;1;3] ;; - : int = 14 inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 18 IV) opérations d'ordre sup sur les séq — opérations Exo : faire de même pour pi (∏) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 19 IV) opérations d'ordre sup sur les séq — opérations oméga peut produire autre chose que des entiers : ● calculs dans ℝ : # (oméga (+.) (function e -> 1. /. (float_of_int e)) [-2;1;3]) - : float = 0.833333333333333259 ● prédicat d'existence vu précédemment : existe : (α → IB) → séq(α) → IB (existe p s) = vrai ssi ∃ ei ∈ s / p(ei) = vrai let existe (p:'a->bool) (s:'a list) : bool = if s = [] then false else (oméga (||) p s) # existe (function e -> e='a') ['o';'c';'a';'m';'l']) - : bool = true inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 20 IV) opérations d'ordre sup sur les séq Typologie des fonctions sur une séquence [e1 ; ... ; en] : 1) Fonctions dont le résultat est scalaire : a) Prédicats : - existence d'un ei satisfaisant une propriété (∃) - tous les ei satisfont une propriété (∀) b) Opérations : - somme des f(ei) (∑) - produit des f(ei) (∏) - opération sur les f(ei) () 2) Fonctions dont le résultat est une séquence : a) Application d'une fonction sur chaque ei b) Sélection des ei vérifiant une propriété inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 21 III) opérations d'ordre sup sur les séq — map 2) Fonctions dont le résultat est une séquence : a) Application d'une fonction sur chaque ei SPÉC valeurs d'une fonction Profil valeurs : (αß) séq(α) séq(ß) Sémant. (valeurs f [e1 ; ... ; en]) = [f e1 ; ... ; f en] Ex (valeurs (e → e2) [-2 ; 1 ; 3]) = [4 ; 1 ; 9] inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 22 III) opérations d'ordre sup sur les séquences — map RÉAL Algo 1 application modèle analyse standard sur les séquences (1) valeurs (2) valeurs [] pr::fin = = ... ... Implémentation 1 let rec valeurs (f:'a->'b) (s:'a list) : 'b list = match s with | [] -> [] [ pr::fin -> (f pr)::(valeurs f fin) NB valeurs définie dans la librairie standard : List.map inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 23 IV) opérations d'ordre sup sur les séquences — map oméga : (ßßß) (αß) séq(α)* ß (oméga opé f [e1 ; ... ; en]) = f(e1) opé ... opé f(en) RÉAL Algo 2 spécialisation de oméga Implémentation 2 let valeurs (f:'a->'b) (s:'a list) : 'b list = if s = [] then [] else (oméga (@) (function e -> [f e]) s) NB valeurs définie dans la librairie standard : List.map inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 24 III) opérations d'ordre sup sur les séquences — map map : (αß) séq(α) séq(ß) map f [e1 ; ... ; en] = [f e1 ; ... ; f en] Exemples d'utilisation de map : ● incrémentation séquence de notes : let incr : int list -> int list = ( map ((+) 1) ) # incr [12 ; 3 ; 20 ; 16] ;; - : int list = [13 ; 4 ; 21 ; 17] let incr : int list -> int list = (map (function n -> if n = 20 then 20 else n+1)) # incr [12 ; 3 ; 20 ; 16] ;; - : int list = [13 ; 4 ; 20 ; 17] inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 25 III) opérations d'ordre sup sur les séquences — map map : (αß) séq(α) séq(ß) map f [e1 ; ... ; en] = [f e1 ; ... ; f en] Exemples d'utilisation de map : ● séquence des admis : let admis : int list -> bool list = (map (function n -> n >= 10)) # admis [13 ; 4 ; 20 ; 17] ;; - : bool list = [true ; false ; true ; true] inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 26 III) opérations d'ordre sup sur les séquences — map b) Sélection dans une séquence des éléments vérifiant une propriété SPÉC Profil selection : (αIB) séq(α) séq(α) Sémant. (selection p s) est la séquence de éléments de s vérifiant p Ex : (selection (e → e > 0) [-2 ; 1 ; 3]) = [1 ; 3] (selection (e → 'a' < e /\ e < 'z') ['O' ;'c' ;'A' ;'m' ;'l']) = ['c' ; 'm' ; 'l'] inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 27 III) opérations d'ordre sup sur les séquences — map RÉAL application modèle analyse standard sur les séquences Algo (1) … (2) ... inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 28 III) opérations d'ordre sup sur les séquences — map Implémentation let rec selection (p :'a->bool) (s :'a list) : 'a list = match s with | [] -> [] | pr::fin -> (if p pr then [pr] else []) @ (selection p fin) Ou | pr::fin -> if p pr then pr ::(selection p fin) else (selection p fin) NB sélection définie dans la librairie standard : List.filter inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 29 III) opérations d'ordre sup sur les séquences — fold 3) fold fold : deux fonctions d'ordre sup très générales ● fold left ● foldright fold : implantent la notion de répétition (les for/while des langages impératifs tel C, C++, Java, ...) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 30 III) opérations d'ordre sup sur les séquences — fold SPÉC Profil foldleft : (ßαß) ß séq(α) ß Sémant. Soit co ∈ ßαß une fonction dite "de combinaison" init ∈ ß une valeur initiale Pour une séquence de deux éléments : (foldleft co init [e1 ; e2]) = (co (co init e1) e2) Pour une séquence de n éléments : (foldleft co init [e1 ; e2 ; ... ; en]) = (co (... (co (co init e1) e2) ...) en) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 31 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Exemple : somme des éléments d'une séquence e1 + ... + en = ((+) (… ((+) ((+) 0 e ) e ) ...) e ) 1 2 n = (foldleft (accu e accu + e) 0 [e1 ; … ; en] ) = (foldleft (+) 0 [e1 ; … ; en]) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 32 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; e2 ; ... ; en]) = (co (... (co (co init e1) e2) ...) en) relation avec les langages impératifs : (foldleft co init s) ⇔ accu ← init répéter pour chaque ei de s : accu ← (co accu ei) renvoyer accu NB : rôle de l'accumulateur joué par le 1er paramètre de co 2ème paramètre de co : élément courant de la liste inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 33 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß RÉAL Algo 1 (foldleft co init [e1 ; e2 ; ... ; en]) = (co (... (co (co init e1) e2) ...) en) découpage à droite de la séquence (1) (foldleft co init []) = init (2) (foldleft co init déb@[der]) = (co (foldleft co init déb) der) Implémentation 1 : analyse par cas + utilisation sélecteurs début et dernier let rec fold_left (co:'b->'a->'b) (init:'b) (s:'a list) : 'b = if s = [] then (* cf éq (1) : *) init else (* cf éq (2) : *) (co (fold_left co init (début s)) (dernier s)) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 34 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß RÉAL (foldleft co init [e1 ; e2 ; ... ; en]) = (co (... (co (co init e1) e2) ...) en) Algo 1 : « facile » à comprendre, mais implémentation peu efficace Algo 2 découpage à gauche de la séquence (1) (foldleft co init pr::fin) = (foldleft co (co init pr) fin) (2) (foldleft co accu []) = accu Implémentation 2 : analyse par cas par filtrage ... NB la librairie standard implante l'algo 2 inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 35 III) opérations d'ordre sup sur les séquences — fold Utilisation de foldleft : difficulté : imaginer co pour réaliser l'opération désirée ! Exemples : ● ● ● ● ● longueur d'une séquence existence d'un élément vérifiant une propriété (∃) somme des f(ei) d'une séquence application d'une fonction sur chaque ei (map) ... inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 36 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Exemple « longueur d'une séquence » : Profil longueur : séq(a) N Soit s = [e1 ; … ; en] ∈ séq(a)* (n ≥ 1) longueur(s) = 1+…+1 = ((+) (… ((+) ((+) 0 1) 1) ...) 1) = (foldleft (accu e accu + 1) 0 s) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 37 III) opérations d'ordre sup sur les séquences — fold longueur s = (foldleft (accu e accu + 1) 0 s) RÉAL Algo 1 utilisation de foldleft Implémentation 1 : let longueur (s:'a list) : int = (fold_left (fun accu _ -> accu + 1) 0 s) ou mieux, par application partielle : let longueur : 'a list -> int = (fold_left (fun accu _ -> accu + 1) inf121 : algorithmique et programmation fonctionnelle 0) 3ème partie : ordre supérieur 29/03/17 38 III) opérations d'ordre sup sur les séquences — fold NB : ⇔ fun x y ... -> function x -> function y -> ... inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 39 III) opérations d'ordre sup sur les séquences — fold foldleft : (ß>αß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Exemple « existence d'un élément vérifiant une propriété » : Profil existe : (α IB) séq(α) IB Soit p : (α IB) et s = [e1 ; … ; en] ∈ séq(α)* (n ≥ 1) (existe p s) = p(e1) ∨ … ∨ p(en) = (∨ (… (∨ faux (p e1)) ...) (p en)) = (foldleft (accu e accu ∨ (p e)) false s) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 40 III) opérations d'ordre sup sur les séquences — fold (existe p s) = (foldleft (accu e accu ∨ (p e)) false s) RÉAL Algo 1 utilisation de foldleft Implémentation 1 : let existence (p:'a->bool) (s:'a list) : bool = (fold_left (fun accu e -> accu || (p e)) false s) Implémentation 2 : par application partielle let existence (p :'a->bool) : 'a list -> bool = (fold_left (fun accu e -> accu || (p e)) false) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 41 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Exemple « somme des f(ei) d'une séquence » : ● Avec foldleft : let sommef (f:'a->int) : 'a list -> int = fold_left (fun accu e -> accu + (f e)) 0 inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 42 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Exemple « valeurs » (List.map) : ● Avec foldleft : let valeurs (f:a->b) : 'a list -> 'b list = fold_left (fun accu e -> accu @ [f e]) [] NB : foldright permet d'éviter l'ajout en queue via @, peu efficace. Exemple : e1 + ... + en = ((+) (… ((+) ((+) 0 en) … e2) e1) = (foldright (e accu → accu+e) [e1 ; … ; en] 0) = (foldright (+) [e1 ; … ; en] 0) D’où : map f = (fold_right (e accu -> (f e) :: accu) []) inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 43 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Profil foldright : (α→ß→ ß) → séq(α) → ß → ß Sémantique (foldright co [e1 ; ... ; en] init) = (co (... (co init en) ...) e1) Réalisation Algo (découpage à gauche de la séquence) (1) (foldright co [] init) = init (2) (foldright co pr::fin init) = (co (foldright co fin init) pr) Implémentation ... / ... inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 44 III) opérations d'ordre sup sur les séquences — fold Exercice Reprendre les exemples précédents avec fold_right inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 45 III) opérations d'ordre sup sur les séquences — fold foldleft : (ßαß) ß séq(α) ß (foldleft co init [e1 ; ... ; en]) = (co (... (co init e1) ...) en) Exemple «sélection » (List.filter) : ● Avec foldleft : let selection (p :'a->bool) : 'a list -> 'a list = fold_left (fun acc e -> acc @ if (p e) then [e] else []) [] inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur 29/03/17 46 III) opérations d'ordre sup sur les séquences inf121 : algorithmique et programmation fonctionnelle 3ème partie : ordre supérieur