diff --git a/Codes.ml b/Codes.ml index 52260c6..f919ef7 100644 --- a/Codes.ml +++ b/Codes.ml @@ -1,61 +1,37 @@ -(* Implémentation des codes linéaires * +(* 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} +* 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 +* 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 +* 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 +* 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) +* 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) *) +#cd "/home/mysaa/Documents/Arbeiten/TIPE2021";; +#use "Maths.ml";; (* La bonne structure *) -type code_lineaire = {k : int; n : int; g : int list; h : int list};; +type code_lineaire = {k : int; n : int; g : matrice; h : matrice};; -(* 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;; +(* Calcule Y = GX *) +let encoder code x = produit code.g x ;; -(* 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 = @@ -71,34 +47,9 @@ let construire_code_lineaire_systematique k n redondance = {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 *) +(* Etant donnés tous 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 @@ -119,9 +70,9 @@ let suivants d vecteurs = 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é *) + +(* 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 @@ -141,26 +92,31 @@ let distance_minimale code = 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' *) +exception PasDansLeCodeException;; + +(* 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 when x = mot_max -> raise PasDansLeCodeException | x -> if (encoder code x) = y then x else iterer (x+1) in iterer 0 ;; -(* Applique notre algorithme préféré *) +exception IndecodableException;; + +(* 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" + | (-1, 0) -> raise IndecodableException | (_, e) -> antecedent code ((lxor) z e) ;; -decoder code_hamming 20;; \ No newline at end of file + + +(* Voilà *) \ No newline at end of file diff --git a/Maths.ml b/Maths.ml new file mode 100644 index 0000000..b9ab12e --- /dev/null +++ b/Maths.ml @@ -0,0 +1,69 @@ +type vecteur = int;; +type matrice = int list;; + +(* Zolie fonction d'affichage (h=nombre de lignes) *) +(* L'algorithme est moche, mais y a pas trop d'autre solution que de arrayiser la liste, c'est stoqué dans le mauvais sens *) +let nthOfBinarint i n = if ((0b1 lsl n) land i)=0 then "0" else "1";; +let print_matrice h (matl:matrice) :unit = + let mat = Array.of_list matl in + let l = Array.length mat in + print_string "┌"; + for i=0 to (l-1) do + print_string (nthOfBinarint mat.(i) 0) + done; + print_endline "â”"; + for j=1 to (h-2) do + print_string "│"; + for i=0 to (l-1) do + print_string (nthOfBinarint mat.(i) j) + done; + print_endline "│"; + done; + print_string "â””"; + for i=0 to (l-1) do + print_string (nthOfBinarint mat.(i) (h-1)) + done; + print_endline "┘";; +let print_vecteur h x = print_matrice h [x];; + +(* Effectue le produit matriciel 'matrice' . 'vecteur' *) +let produit (matrice:matrice) (vecteur:vecteur) :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 +;; + +(* Ne calcul papy *) +let deux_puissance = (lsl) 1;; + + +(* 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) +;; + + +(* Change l'état du 'i'-eme bit *) +let changer_bit i = (lxor) (deux_puissance i);; + + + + + + +(* Vérifie que 'y' respecte toutes les contraintes de 'cs' *) +(* Est-ce que pour tout P dans cs, P(cs) ? *) +let respecter y cs = + let ny = (lnot) y in + List.fold_right (fun c b -> b && (land) c ny > 0) cs true +;; + diff --git a/Maths.mli b/Maths.mli new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/Maths.mli @@ -0,0 +1 @@ + diff --git a/TODO b/TODO new file mode 100644 index 0000000..0fbb6a6 --- /dev/null +++ b/TODO @@ -0,0 +1,10 @@ + +----- Mais qu'est-ce qu'on doit faire ? ----- + +Implémenter les codes cycliques. +- Génération à partir d'un polynôme. +- Récupérer le polynôme générateur. + +Regarder ce que sont les codes BCH + +Réécrire correctement les papiers lus. diff --git a/Test.ml b/Test.ml new file mode 100644 index 0000000..367b64b --- /dev/null +++ b/Test.ml @@ -0,0 +1,45 @@ +#cd "/home/mysaa/Documents/Arbeiten/TIPE2021";; +#use "Codes.ml";; + +(* Test du produit de matrice *) +let matest = [0b01110; 0b00101; 0b10111];; +print_matrice 5 matest;; +produit matest 0b110;; (* -> 0b10010 = 8*) + +(* Test des fonctions de base *) +deux_puissance 11;; +identite 3;; +changer_bit 2 6;; +respecter 7 [3];; + + +(* Test des Codes *) +(* 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] +;; +let code_paparfait = + construire_code_lineaire_systematique +print_vecteur 6 (encoder code_hamming 6);; + + +print_matrice 3 (suivants 3 (suivants 3 (suivants 3 (suivants 3 [0b000]))));; + +distance_minimale code_hamming;; + + +print_vecteur 7 (encoder code_hamming 0b0100);; +decoder code_hamming 0b1010100;; +decoder code_hamming 0b0010100;; +decoder code_hamming 0b1110000;; +print_vecteur 7 21;;