(* 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) *) #cd "/home/mysaa/Documents/Arbeiten/TIPE2021/";; #load "Math.cmo";; open Math;; (* La bonne structure *) type code_lineaire = {klin : int; nlin : int; g : matrice; h : Math.matrice};; (* La super stucture *) type code_cyclique = {kcyc : int; ncyc: int; pol: polynome};; (* Calcule Y = GX *) let encoder code x = produit code.g x ;; (* 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 {klin = k; nlin = n; g = g; h = h} ;; (* Construit le code linéaire associé au code cyclique *) let cycliqueVersLineaire code = let k=code.kcyc and n=code.ncyc and pol=code.pol in let g = let rec itdecal i l = if i<0 then l else itdecal (i-1) ((pol lsl i)::l) in itdecal (k-1) [] and h = let polh = poldiv ((deux_puissance n) + 1) pol in print_polynome polh; let filtre = (deux_puissance (n-k+1))-1 in let rec sub i l = if i<(-k) then l else sub (i-1) (((decagauche polh i) land filtre)::l) in sub (n-k-1) [] in {klin = k; nlin = n; g = g; h = h} ;; let lineaireVersCyclique code = (*TODO*)1 ;; (* 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 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 ;; (* 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.nlin in let propriete = fun v -> (0 < v) && (appartenir code v) in let (p, _) = plus_petit_verifiant propriete n n in p ;; 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.klin) - 1 in let rec iterer = function | x when x = mot_max -> raise PasDansLeCodeException | x -> if (encoder code x) = y then x else iterer (x+1) in iterer 0 ;; 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.nlin in let propriete = fun v -> appartenir code ((lxor) z v) in match plus_petit_verifiant propriete e_c n with | (-1, 0) -> raise IndecodableException | (_, e) -> antecedent code ((lxor) z e) ;; (* Voilà *)