From 73110df861410fdb989b513b9a8a7ce078d1f73a Mon Sep 17 00:00:00 2001 From: Mysaa Date: Wed, 24 Feb 2021 21:57:14 +0100 Subject: [PATCH] Ajout du super code de Victor ! --- Codes.ml | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 Codes.ml diff --git a/Codes.ml b/Codes.ml new file mode 100644 index 0000000..52260c6 --- /dev/null +++ b/Codes.ml @@ -0,0 +1,166 @@ +(* Implémentation des codes linéaires * + +* un code linéaire est une application linéaire f de S = {0,1}^k dans D = {0,1}^n injective +* le terme code désigne aussi l'espace C = Im(f) +* k représente la dimension de l'espace source, on l'appelle dimension du code +* n représente la dimension de l'espace des codes, on l'appelle longueur du code +* on modèlise un code linéaire par sa matrice génératrice G, celle-ci possède n lignes et k colonnes, elle est à coefficients dans {0,1} +* tout calcul matriciel se fait dans le corps F_2 +* nous nous intéressons dans un premier temps à des codes systématiques càd recopiants le mot d'entré puis rajoutants des redondances +* pour aider le décodage on introduit le concept de matrice de contrôle H dont on n'a pas l'unicité, il s'agit d'une matrice comportant n-k lignes et n colonnes et dont le noyau correspond à l'image du code +* la distance minimale d_f d'un code correspond à la plus petite distance séparant deux mots distincts du code +* on définit à partir de celle-ci la capacité de détection e_d du code ainsi que celle de correction e_c +* un code est parfait si pour tout mot de code M de D, il existe un unique Y appartenant à C minimisant la distance de M à Y + +* on souhaite transmettre un mot source X, pour ce faire on l'encode en Y = f(X) puis on envoit Y, après transmission (et donc des apparitions d'erreurs) est reçu Z +* notre but est de construire un algorithme capable de déterminer le mot de code Y' le plus proche de Z et donc de décoder Z en X' = f<-1>(Y') +* on pose E = Z + Y le mot d'erreur associé à Z +* pour M un mot de code, on appelle syndrome de M le mot HM, on note en particulier S le syndrome de Z +* en remarquant que E est dans la classe lattérale de Z (càd qu'il a le même syndrome que Z), la recherche de Y' se ramène à celle du mot de plus petit poids (au sens de Hamming) dans la classe lattérale de Z + +*NOTE SUR LA PROGRAMMATION* +* on représente un vecteur dans F_2 par un entier dont la décomposition binaire correspond aux composantes du vecteur +* on représente une matrice par un liste d'entier, il s'agit de la liste de ses colonnes (qui sont donc des vecteurs) + +*) + +(* La bonne structure *) +type code_lineaire = {k : int; n : int; g : int list; h : int list};; + +(* Effectue le produit matriciel 'matrice' . 'vecteur' *) +let produit matrice vecteur = + let rec auxiliaire resultat_partiel masque = function + | [] -> resultat_partiel + | colonne :: reste -> + let resultat = + if masque mod 2 = 1 + then (lxor) colonne resultat_partiel + else resultat_partiel + in auxiliaire resultat (masque / 2) reste + in auxiliaire 0 vecteur matrice +;; +produit [14; 5; 23] 6;; + +(* Calcul Y = GX *) +let encoder code x = produit code.g x;; + +(* Ne calcul papy *) +let deux_puissance = (lsl) 1;; +deux_puissance 11;; + +(* Construit la matrice identité de taille d.d *) +let identite d = + let rec sub acc = function + | p when p >= 0 -> sub ((deux_puissance p) :: acc) (p-1) + | _ -> acc + in sub [] (d-1) +;; +identite 3;; + +(* Le nom de cette fonction n'est pas assez explicite *) +let construire_code_lineaire_systematique k n redondance = + let g = + let decalage = deux_puissance k in + let rec iteredon ajout = function + | [] -> [] + | tete :: queue -> + let c = tete * decalage + ajout in + c :: (iteredon (ajout * 2) queue) + in iteredon 1 redondance + and h = redondance @ (identite (n-k)) in + {k = k; n = n; g = g; h = h} +;; + +(* Un classique : code de Hamming (4, 7) + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 + 0 0 0 1 + 1 1 1 0 1 0 0 + 1 1 0 1 0 1 0 + 1 0 1 1 0 0 1 +-> les 4 premières colonnes : G +-> les 3 dernières lignes : H +*) +let code_hamming = + construire_code_lineaire_systematique 4 7 [7; 3; 5; 6] +;; +encoder code_hamming 6;; + +(* Change l'état du 'i'-eme bit *) +let changer_bit i = (lxor) (deux_puissance i);; +changer_bit 2 6;; + +(* Vérifie que 'y' respecte toutes les contraintes de 'cs' *) +let respecter y cs = + let ny = (lnot) y in + List.fold_right (fun c b -> b && (land) c ny > 0) cs true +;; +respecter 7 [3];; + +(* Etant donné touts les vecteurs de poids p dans un espace de dimension d, retourne touts ceux de poids p+1 dans ce même espace *) +let suivants d vecteurs = + let contraintes = ref [] in + let resultats = ref [] in + let rec iterer = function + | [] -> () + | x :: r -> + let donne_un_resultat = ref false in + for i=0 to d-1 do + let y = changer_bit i x in + if x < y && (respecter y !contraintes) + then begin + resultats := y :: !resultats; + donne_un_resultat := true; + end; + done; + if !donne_un_resultat + then contraintes := x :: !contraintes; + iterer r; + in iterer vecteurs; !resultats +;; +suivants 3 [7];; + +(* Renvoit le plus petit mot (au sens de Hamming) dans F_2^d vérifiant 'propriete' et de poids inférieur à poids_max. Renvoie le couple (-1, 0) si aucun mot n'a été trouvé *) +let plus_petit_verifiant propriete poids_max d = + let rec chercher p vecteurs = + match List.find_opt propriete vecteurs with + | Some v -> (p, v) + | None -> + if p < poids_max + then chercher (p+1) (suivants d vecteurs) + else (-1, 0) + in chercher 0 [0] +;; + +let appartenir code v = produit code.h v = 0;; + +(* Calcul la distance minimale d'un code *) +let distance_minimale code = + let n = code.n in + let propriete = fun v -> (0 < v) && (appartenir code v) in + let (p, _) = plus_petit_verifiant propriete n n in p +;; +distance_minimale code_hamming;; + +(* Calcul de façons à ouf l'antécédent de 'y' pour le code 'code' *) +let antecedent code y = + let mot_max = (deux_puissance code.k) - 1 in + let rec iterer = function + | x when x = mot_max -> failwith "y n'appartient pas au code" + | x -> + if (encoder code x) = y + then x else iterer (x+1) + in iterer 0 +;; + +(* Applique notre algorithme préféré *) +let decoder code z = + let d_min = distance_minimale code in + let e_c = (d_min - 1) / 2 and n = code.n in + let propriete = fun v -> appartenir code ((lxor) z v) in + match plus_petit_verifiant propriete e_c n with + | (-1, 0) -> failwith "on ne peut décoder" + | (_, e) -> antecedent code ((lxor) z e) +;; +decoder code_hamming 20;; \ No newline at end of file