TIPE2021/Test.ml

527 lines
12 KiB
OCaml

#cd "/home/mysaa/Documents/Arbeiten/TIPE2021";;
Sys.command "make Math.cmo Code.cmo";;
#load "Math.cmo";;
#load "Code.cmo";;
open Math;;
open Code;;
let print_boolean b = match b with
| true -> print_string "true"
| false -> print_string "false";;
let codeh = CLineaire.systematiqueFromRedondance 4 7 [3;6;9;12];;
let vecteurs = matriceAuPif 99 (8-1);;
print_matrice 4 vecteurs;;
let classes = CLineaire.genererClasses codeh;;
let test v = try
CLineaire.encoder codeh (CLineaire.decoder codeh v) <> CLineaire.decoder2 classes v
with
Code.CLineaire.PasDansLeCodeException -> (print_int v;print_endline "*";false)
| CLineaire.IndecodableException -> (print_int v;print_endline "-";false) in
List.find_opt test vecteurs;;
CLineaire.decoder codeh 49;;
CLineaire.encoder codeh 1;;
CLineaire.decoder2 classes 49;;
exit 0;;
(* Test du produit de matrice *)
let matest = [0b01110; 0b00101; 0b10111];;
print_matrice 5 matest;;
produit matest 0b110;; (* -> 0b10010 = 8 *)
(* Tests des polynomes *)
let pol1 = 13 and pol2 = 67;;
print_polynome pol1;;
print_polynome pol2;;
print_polynome (polmul pol1 pol2);;
let qt,rst=(poldiveuc pol2 pol1) in
print_polynome qt;
print_polynome rst;;
(* 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 =
CLineaire.systematiqueFromRedondance 4 7 [7; 3; 5; 6]
;;
CLineaire.distance_minimale code_hamming;;
exception GTROUVE of matrice;;
for i=0 to 20
do
Random.self_init ();
let matPapa = matriceAuPif 9 12 in
let code_paparfait = CLineaire.systematiqueFromRedondance 12 21 matPapa in
let dst = CLineaire.distance_minimale code_paparfait in
if dst>1
then raise (GTROUVE matPapa)
done;;
print_vecteur 7 (CLineaire.encoder code_hamming 0b0100);;
CLineaire.decoder code_hamming 0b1010100;;
CLineaire.decoder code_hamming 0b0010100;;
CLineaire.decoder code_hamming 0b1110000;;
print_vecteur 7 21;;
(* Tests des codes cycliques *)
let cocycl = CCyclique.get 7 4 13;;
print_polynome cocycl.pol;;
poldiveuc ((deux_puissance 7) +1) cocycl.pol;;
print_polynome ((deux_puissance 7) +1);;
print_polynome (poldiv ((deux_puissance 7) +1) cocycl.pol);;
let cocylined = cycliqueVersLineaire cocycl;;
print_matrice 7 cocylined.g;;
print_matrice 4 cocylined.h;;
CLineaire.distance_minimale cocylined;;
print_vecteur 9 203;;
(****** Construction des classes cyclotomiques pour un degré n ******)
let classes n =
let rech = Array.make n false in
let lsts = ref [] in
for i=1 to (n-1)
do
if not rech.(i)
then
begin
let v = ref (i lsl 1) in
let lst = ref [i] in
rech.(i) <- true;
while !v<>i
do
rech.(!v) <- true;
lst := !v::!lst;
v := (!v lsl 1) mod n(*Fois 2*)
done;
lsts := !lst::!lsts
end
done;
!lsts;;
let clzLst = let e::s = classes 31 in e;;
let tbleLst = let e::s = trouve 31 in e;;
let clz = List.map (fun x -> Ap(x)) clzLst;;
let tble = Array.map (fun x -> Ap(x)) tbleLst;;
(* Multiplie le polynome arr par chaque élément de la classe. On a deg(out)=d*)
let rec mulan tble arr clz d =
match clz with
| [] -> ()
| a::rr ->
mulan tble arr rr (d-1);
arr.(d) <- arr.(d-1);
for i=d-1 downto 1
do
arr.(i) <- add tble arr.(i-1) (mul tble a arr.(i))
done;
arr.(0) <- mul tble a arr.(0)
;;
let pols clz tble =
let len = List.length clz in
let poly = Array.make (len+1) Zero in
poly.(0) <- Ap(0);
mulan tble poly clz (len);
poly;;
let rec polof tble p a =
if p=0 then Zero else
let cst = if (p mod 2=0) then Zero else Ap(0) in
let q = p lsr 1 in
add tble cst (mul tble a (polof tble q a));;
let pomin tble a =
if a=Zero then 2 else
let i = ref 1 in
while polof tble !i a <> Zero
do
incr i;
incr i
done;
!i;;
polof tble 4 (Ap(2));;
for i=0 to 31 do
print_int i;
print_string "->";
print_polynome (pomin tble (Ap(i)))
done;;
pols clz tble;;
(* Essayons de générer une table d'addition *)
(* ABORT MISSION *)
(**** Utilitaires ****)
let rangearray i j =
let out = Array.make (j-i+1) 0 in
for k=i to j do
out.(k-i) <- k
done;
out;;
let shuffle tab =
let n = Array.length tab in
for i=n-2 downto 1 do
let j = Random.int (i+1) in
let a,b=tab.(i),tab.(j) in
tab.(i) <- b;
tab.(j) <- a
done;;
exception EmptyException;;
let pop q = match !q with
| [] -> raise EmptyException
| e::s -> q:=s;e;;
let push q e = q:=e::!q;;
let printtbl arr=
let n = Array.length arr in
print_string "[|";
print_int arr.(0);
for i=1 to (n-1) do
print_string ";";
print_int arr.(i)
done;
print_string "|]";;
let printlst lst =
print_string "[";
match lst with
| [] -> ()
| e::s -> begin
print_int e;
let rec aux ll = match ll with
| [] -> ()
| h::t -> print_string ";";print_int h;aux t
in aux s end;
print_string "]";;
exception FoundException;;
let arrmem arr e =
let n = Array.length arr in
try
for i=0 to n-1 do
if arr.(i)=e then raise FoundException
done;
false
with FoundException -> true;;
let rec foreache lst f edd= match lst with
| [] -> edd ()
| e::s -> f e;foreache s f edd;;
let foreach lst f = foreache lst f (fun () -> ());;
(**** La zolie structure****)
let n = 7;;
type element = Zero | Ap of int;;
exception NotApException;;
let getap a = match a with
| Zero -> raise NotApException
| Ap(i) -> i;;
let add tble i j =
let n = (Array.length tble) +1 in
if i=j then Zero else
match i,j with
| Zero,x | x,Zero -> x
| (Ap(0),Ap(k)) -> tble.(k-1)
| (Ap(k),Ap(0)) -> tble.(k-1)
| (Ap(ii),Ap(jj)) -> let tt = getap (tble.(((jj-ii+n) mod n)-1)) in
Ap((tt+ii) mod n);;
let mul tble i j =
let n = (Array.length tble)+1 in
match i,j with
| Zero,_ | _,Zero -> Zero
| Ap(i),Ap(j) -> Ap((i+j) mod n);;
let randtabl n =
let tab = rangearray 1 (n-1) in
Random.self_init ();
shuffle tab;
let rout = Array.make (n-1) Zero in
for i=0 to n-1-1 do
rout.(i) <- Ap(tab.(i))
done;
rout;;
let getphi arr k = Ap(arr.(k));;
exception PasTransitifException;;
let estTransitif tble =
let n = Array.length tble in
try
for i=1 to (n-1) do
for j=1 to (i-1) do (* i et j distincts et non nuls (transititivité évidente)*)
if (* La formule s'applique *) i<>tble.(j) && j <> tble.(i) then
let sa = j + tble.((tble.(i)-j+n) mod n) in
let sb = i + tble.((tble.(j)-i+n) mod n) in
if sa mod n <>sb mod n then raise PasTransitifException
done
done;
true
with PasTransitifException -> false;;
let printalp a = match a with
| Zero -> print_string "o"
| Ap(i) -> print_int i;;
(* Cette fonction utilise les super formules en partant de
la valeur indiquée *)
exception ContradictionException of int * int array;;
(* Renvoie la LISTE des valeurs non associées dans arr *)
(* Suppose que arr\{-1} est bijective (assurée par l'involutivité de phi) *)
(* Bien entendu, on oublie le zéro *)
let missingValues arr =
let n = Array.length arr in
let rec aux arr i l =
if i=0 then l else
if (arr.(i)=(-1)) then
aux arr (i-1) (i::l)
else aux arr (i-1) l
in aux arr (n-1) [];;
(* Remplis la table avec les valeurs qu'impliquent la valeur en k, supposée déjà
imposée par une fonction exterieure. Renvoie une ContradictionException si l'une
des implications est impossible avec une des valeurs déjà mises, ou impliquées
d'une autre manière *)
let remplis tble k =
let n = Array.length tble in
let queue = ref [k] in
while !queue<>[]
do
let el = pop queue in
(* Test de l'involutivité *)
begin
match tble.(tble.(el)) with
| -1 -> (tble.(tble.(el)) <- el;push queue tble.(el))
| x when x=el -> ()
| _ -> raise (ContradictionException(el,tble))
end;
(* Test de la formule d'opposition *)
let opv = (n+tble.(el)-el) mod n in
match tble.(n-el) with
| -1 -> (tble.(n-el) <- opv;push queue (n-el))
| x when x=opv-> ()
| _ -> raise (ContradictionException(el,tble))
done;;
(* Efface (met -1) dans les cases de tble d'index les éléments de mv (liste) *)
let rec cleanTable tble mv = match mv with
| [] -> ()
| e::s -> tble.(e) <- (-1);cleanTable tble s;;
(* Rajoute à la pile d'entrée, à partir d'un tableau représentant une fonction phi partielle (-1 pour
les valeurs encore indéfinies) l'ensemble de toutes les fonctions phi réelles
respectant la transitivité (créant donc un corps) et étendant la fonction partielle. *)
let rec exploite tble res =
let mv = missingValues tble in
match mv with
| [] -> if estTransitif tble then push res tble (* Toutes les valeurs sont fixées: pas quarante-douze solutions ...*)
| k::r -> (* On séléctionne un des éléments indéfinis. On va tester toutes les valeurs sur lui *)
let rec traite tble k mv mm res =
(* Traite à partir de la table tble, l'index de tests k, les valeurs manquantes mv,
et les valeurs manquantes pas encore essayées mm, res la pile où mettre les bons *)
begin
match mm with [] -> () (* Alors, on a testé toutes les valeurs manquantes *)
| m::rr -> (* On doit tester arr.(k)<-m, puis reste tout rr à tester *)
if k<>m then (* Un point ne peut etre son image *)
begin
cleanTable tble mv; (* Enlève toutes les valeurs des essais précedents *)
tble.(k) <- m; (* Place la bonne valeur de test s*)
begin
try
remplis tble k; (* Tente de remplir avec les implications le l'index k*)
if arrmem tble (-1) (* Si des cases restent indéterminées malgrès notre valeur arr.(k) *)
then (* On déscend d'un étage *)
(exploite tble res)
else (* Ben on sauvegarde si c'est effectivement transitif et on continue *)
if (estTransitif tble) then push res (Array.copy tble)
with ContradictionException(el,arr) -> () (* Si il y a eu une contradiction on ne stoque rien, ni n'essaye rien*)
end(*try*)
end(*if k<>m*);
traite tble k mv rr res (* Dans tous les cas, on teste le reste *)
end
in traite tble k mv mv res;; (* On applique la fonctions auxilière *)
(* Fonction faisant appel à exploite afin de renvoyer la liste-ensemble des tables créant un
corps sur {0}u{a pow k pour k dans [0,n-1] *)
let trouve n =
let arr = (Array.make n (-1)) in
arr.(0) <- 0;
let res = ref [] in
exploite arr res;
!res;;
(** Tests **)
for m=1 to 10 do
let i = (1 lsl m)-1 in
let t0 = Sys.time () in
print_int i;
foreach (trouve i) printtbl;
print_endline ";";
print_string "Temps écoulé: ";
print_float ((Sys.time ()) -. t0);
print_endline "."
done;;
(**** CRIBLE DE POLYNOMSTENE ****)
let polynomstene pp : polynome list=
let n=degre pp in
let irrs = Array.make (1 lsl (n+1)) true in (* irrs.(p)=true si p est irréductible *)
let p = ref pp in (* Le «gros» polynome va diminuer *)
(* Marque les multiples de q comme non irréductibles, si leur degré est inferieur à celui de p*)
let annuleMultiples q p =
let t = ref 2 in (* On commence par multiplier par X *)
let r = ref (polmul !t q) in
while !r < p
do
irrs.(!r) <- false;
incr t;
r := polmul !t q
done
in
let q = ref 2 in
let divs = ref [] in
while (!p<>1)
do
if irrs.(!q)
then begin
annuleMultiples !q !p;
let (d0,r0) = poldiveuc !p !q in
let d = ref d0 and r = ref r0 in
while (!r=0)
do (* q divise p *)
divs := !q::!divs;
p := !d;
let (d0,r0) = poldiveuc !p !q in
d := d0;
r := r0
done
end;
incr q
done;
!divs;;
let naifostene pp =
let p = ref pp in (* Le «gros» polynome va diminuer *)
let q = ref 2 in
let divs = ref [] in
while (!p<>1)
do
let (d0,r0) = poldiveuc !p !q in
let d = ref d0 and r = ref r0 in
while (!r=0)
do (* q divise p *)
divs := !q::!divs;
p := !d;
let (d0,r0) = poldiveuc !p !q in
d := d0;
r := r0
done;
incr q
done;
!divs;;
let pol = (1 lsl 61) lxor 1;;
print_polynome pol;;
let lst = naifostene pol;;
List.iter (function p -> print_polynome p) lst;;
print_polynome (List.fold_left polmul 1 lst);;
(*** Test de recherche du polynome minimal de alpha ***)
type complexe = float*float;;
let cmul x y =
let (a,b)=x and (c,d)=y in
(a*.c-.b*.d,b*.c+.a*.d);;
let cadd x y =
let (a,b)=x and (c,d)=y in
(a+.c,b+.d);;
let rec polymise p z =
if p=0 then (0.,0.)
else
let a = if p mod 2 = 0 then (0.,0.) else (1.,0.) in
let q = p lsr 1 in
cadd a (cmul z (polymise q z));;
let n = 21;;
let alpha =
let th = 2.*.3.14159265358979/.(float_of_int n) in
(cos th,sin th);;
let isNull z =
let epsilon = 0.00001 in
let (a,b)=z in
-.epsilon<a && a<epsilon && -.epsilon<b && b<epsilon;;
for p=1 to 2 lsl 21
do
if isNull (polymise p alpha)
then(
print_int p;
print_polynome p)
done;;