Informatique_algorithmique Projet_0 Bousquet But : - Nicolas et Recherche de nombres premiers. Méthodes de construction de carrés magiques et diaboliques. Tests pour vérifier le caractère magico-diabolique (MD) d’une matrice. Tests pour savoir empiriquement pour quelle taille N les carrés sont diaboliques. Plan : - p1 - Plan + Introduction. - p2 - Le crible d’Erathostène. - p2-3 - Méthode par division. - p3-4 - La construction de carrés magiques. - p4-5 - La construction de carrés diaboliques. - p5-7 - Tests du caractère MD. - p7-9 - Test sur la taille N. (application du travail sur les nombres premiers). - p9-10 - Le menu. - p10 - Conclusion. Introduction : Nous allons étudier dans un premier temps deux algorithmes de recherche des nombres premiers : Le crible d’Erathostène et la méthode par division des précédents nombres premiers. Nous nous intéresserons ensuite aux méthodes de construction de carrés magiques ou diaboliques ainsi qu’à l’élaboration de test servant à vérifier si un carré est magique ou diabolique et dans quels cas seulement il peut l’être. Les constructions des carrés se feront à l’aide des matrices de matlab. NB : algorithmes en matlab. Le Crible d’Erathostène : (crible.m) Le principe du crible : Pour N entier donné, nous allons regardé, en partant de 1 et allant jusqu’à N, si chacun des nombres est « barré » ou non. S’il n’est pas barré alors c’est un nombre premier. En effet : initialisons un tableau de N entiers (de 1 à N) et barrons 1 et 2 car il ne sont pas premiers, l’algorithme va consister à barré tous les multiples de chaque nombre premier rencontré (donc un nombre premier non barré) en partant de l’entier 3 qui est premier. NB : on ne regarde que les nombres impairs, un nombre pair ne pouvant pas être premier. Le code correspondant au crible est : function np=crible(n) %--Crible d’Erathostène. %--Input : un entier n positif supérieur à 3. %--Output : le vecteur rempli de nombres premiers % inférieur à n. %--Remplissage du tableau de 1 à n : for i=1:n c(i)=i; end %--Initialisation: np(1)=1; np(2)=2; l=2; %--Boucle: for k=3:2:n if c(k)==k l=l+1; np(l)=k; for i=(3*k):k:n c(i)=0; end end end %--par pas de 2 : nombres impairs %--on regarde si le k-ème n’est % pas “barré”, on incrémente l, % on écrit la valeur de k dans % le vecteur np, on met à zéros % (on “barre”) tout les multiples % de k. %--on écrit la valeur de np, qui % contient les nombres premiers % inférieur ou égal à N. Méthode par division : (np.m) Le principe de la méthode par division : Pour N entier donné on va regarder, après avoir initialisé un vecteur p (p(1)=1, p(2)=2, p(3)=3), si le nombre k (partant de 4 à N) est divisible par tout les nombres premiers inférieurs à lui-même : s’il ne l’est pas alors k est premier et est rajouté à la liste p des nombres premiers, sinon on ne fait rien et on passe à k+1. Le code correspondant est : function np=np(n) %--Affichage d’un vecteur contenant tout les nombres premiers % de 3 à n. %--Input : N entier strictement positif. %--Output : le vecteur en question. %--Initialisation : np(1)=1; np(2)=2; np(3)=3; l=3; %--Boucle : for k=5:2:n d=0; for i=3:l if (mod(k,np(i)))==0 d=1; break end end if d==0 l=l+1; np(l)=k; end End %--de 5 à n par pas de 2 on ne % regarde que les nombres % impairs. %--critère de divisibilité. %--incrémentation de l et % écriture de k à la l-ème % place. %--écriture du vecteur np. Construction de carrés magiques : (magic.m) Une des méthodes de construction que nous allons utiliser est seulement valable au cas N entier naturel impair. Algorithme de construction : Pour un carré de taille N on remplit préalablement notre matrice de zéros (N² zéros) puis on se place à la (N+1)/2 ème ligne et (N+3)/2 ème colonne et on écrit 1. Supposons maintenant que nous soyons à l’étape k, ayant écrit la (k-1)-ème valeur dans la case adaptée. A l’étape suivante nous allons décrémenter i (indice de ligne) et incrémenter j (indice de colonne) et regarder si la case contient un zéro : si oui on écrit la valeur suivante k, sinon on incrémente i et incrémente j encore une fois et on écrit la valeur k à la nouvelle case obtenue. L’algorithme se poursuit alors. Si un déplacement de ligne ou de colonne est nécessaire on se place à la ligne ou colonne opposée correspondante (comme si l’espace était torique). Le code correspondant est : function A=magic(n) %--Carré magique avec un nombre impaire. %--Input : un entier positif impair. %--Output : la matrice magique de taille N. %--Test sur la parité de n : if mod(n,2)==0 error('n pas impaire'); end %--Initialisation : A=zeros(n); i=(n+1)/2; j=(n+3)/2; A(i,j)=1; %--Boucle de remplissage : for k=2:n^2 i=i-1; test=0; if i==0 i=n; end while ~test j=j+1; if j==n+1 j=1; end if A(i,j)==0 test=1; else i=i+1; if i==n+1 i=1; end end end A(i,j)=k; end %--Affectation de la valeur. Construction de carrés diaboliques : (diabolic.m) On demande à l’utilisateur de rentrez un entier positif N. Nous verrons par la suite quels sont les N qui permettent de construire un carré diabolique. Algorithme de construction : On applique la méthode du cavalier. Je remplis préalablement ma matrice de zéros. Je place mon 1 de départ dans n’importe quel case de la matrice. Supposons que je me trouve à la k+1-ème valeur et que je viens de placer la k-ème à la case de coordonnée (i,j), alors si k n’est pas multiple de N le mouvement du cavalier impose une décrémentation de i de 2 (i :=i-2 ) et une incrémentation simple de j, sinon je ne fais qu’incrémenter i et je place la valeur k+1 à cette nouvelle case. On continue jusqu’à remplir complètement la matrice. Le code correspondant est : function A=diabolic(n,i,j) %--Carré diabolique de n sur n en partant de la case (i,j). %--Input : n=dimension , (i,j)=coordonées de départ. %--Output : carré diabolique. %--Initialisation : A(i,j)=1; %--Cas d’erreurs : if (i>n)|(i<=0)|(j>n)|(j<=0) error('i et j pas compris dans la dimension ') end if (n<=0) error('n doit etre positif') end %--Boucle de remplissage : for k=2:(n^2) if mod(k-1,n)==0 i=i+1; if i==n+1 i=1; end else i=i-2; if i<=0 i=n+i; end j=j+1; if j==n+1 j=1; end end A(i,j)=k; end Cette méthode ne marche correctement que pour certaines valeurs de N. (voir Test sur la taille N p7). Test du caractère MD : (testdiabolic.m) Dans cet algorithme nous allons vérifier si une matrice donnée est, déjà, magique et ensuite si elle est diabolique. Pour ce faire nous allons comparer différentes sommes à une valeur de référence qui peut être la somme sur la première ligne des coefficients. Les différentes sommes à considérer sont : Pour le carré magique, les sommes sur : - les lignes - les colonnes - les deux diagonales (diagonale et anti-diagonale) Pour le carré diabolique il faut rajouter les sommes sur : - les pseudos diagonales - les anti-pseudos diagonales Le code correspondant est : function y=testdiabolic(A) %--Test si A est magique, diabolique ou rien-%--Input : la matrice a tester-%--Output : le caractere magique, diabolique-%--Creation de deux vecteurs contenant les sommes sur les % lignes et colonnes-sumlign=sum(A); sumcolon=sum(A'); %--Initialisation-taille=size(A,1); n=taille; %-----------------%---TEST SI LA MATRICE EST MAGIQUE--%--Test si la matrice est carré-if taille~=size(A,2) error('A non magique'); end %--------------------------------%--Comparaison sur la 1ere ligne et colonne-if sumlign(1)~=sumcolon(1) error('A non magique') end %--------------------------------%--Comparaison sur les lignes et les colonnes-for i=2:taille if sumlign(1)~=sumlign(i) error('A non magique'); end if sumlign(1)~=sumcolon(i) error('A non magique'); end end %---------------------------------------------%--Sur la diagonale-if sumlign(1)~=sum(diag(A)) error('A non magique'); end %-------------------%--Sur l'antidiagonale-w=0; for j=1:taille w=w+A(j,taille-j+1); end if w~=sumlign(1) error('A non magique'); end %----------------------disp('A est magique'); %---------------------------------------------%---TEST SI LA MATRICE EST DIABLOLIQUE--for k=1:n-1 t=0; for i=1:n-k t=t+A(i,i+k); end for i=n-k+1:n t=t+A(i,i+k-n); end if t~=sumlign(1) error('A non diabolique'); end u=0; for i=1:k u=u+A(i,k-i+1); end for i=k+1:n u=u+A(i,n+k-i+1); end if u~=sumlign(1) error('A non diabolique'); end end %----------------------------------------------------disp('A est diabolique'); Test sur la taille N : (testdim.m) Nous voulons savoir pour quels entiers positifs n une matrice est diabolique en appliquant la méthode de construction précédente. On demande alors à l’utilisateur de rentrer un entier positif N et allons ensuite construire N matrices de taille allant de 2 à N par le procédé du cavalier et vérifier leur caractère diabolique. Nous devons fixer un point de départ de l’algorithme : le chiffre 1 sera placé en position (1,1). Nous avons introduit une fonction (booleendiab.m) qui, à partir d’une matrice donnée, renvoie 1 si la matrice est diabolique, 0 sinon. La fonction testdim se sert alors de booleendiab pour tester chaque matrice créée par testdim. Le code de booleendiab.m est : function b=booleendiab(A) %--Test si A est diabolique-%--Input : la matrice a tester-%--Output : le caractere booleen 1 diabolique 0 non-%--Creation de deux vecteurs contenant les sommes sur les % lignes et colonnes-sumlign=sum(A); sumcolon=sum(A'); %--Initialisation-taille=size(A,1); n=taille; b=1; %-----------------%---TEST SI LA MATRICE EST DIABLOLIQUE--%--Test si la matrice est carré-if taille~=size(A,2) b=0; end %--------------------------------%--Comparaison sur la 1ere ligne et colonne-if sumlign(1)~=sumcolon(1) b=0; end %--------------------------------%--Comparaison sur les lignes et les colonnes-for i=2:taille if sumlign(1)~=sumlign(i) b=0; end if sumlign(1)~=sumcolon(i) b=0; end end %--------------------------------%--Test sur les diagonales et antidiagonales-for k=0:n-1 t=0; for i=1:n-k t=t+A(i,i+k); end for i=n-k+1:n t=t+A(i,i+k-n); end if t~=sumlign(1) b=0; end u=0; for i=1:k u=u+A(i,k-i+1); end for i=k+1:n u=u+A(i,n+k-i+1); end if u~=sumlign(1) b=0; end end %----------------------------------------------------- Le code de testdim.m est : function p=testdim(n) %--Input : n pour tester si les matrices de dimension % <= n sont diabolique ou non. %--La place du premier élément n'a pas d'importance. %--Output : les valeurs i comprises entre 1 et n dont la matrice % de dimension i n'est pas diabolique. l=0; for i=3:n drapeau=0; A=diabolic(i,1,1); if booleendiab(A) drapeau=1; end if drapeau==1 l=l+1; p(l)=i; end end On constate que la function testdim renvoie le vecteur des nombres premiers inférieurs ou égaux à N complétés des nombres s’écrivant 5*(nombre premier) suivant : (ex : pour N=50) testdim(50) ans = 5 7 11 13 17 19 23 25 29 31 35 37 41 43 47 49 Pour N très grand il suffit de comparer ce vecteur avec celui que l’on obtient avec les méthodes de recherche des nombres premiers décrites précédemment.(Il faut alors rajouter les nombres 5*p, p premier à la liste). On peut alors dégagé une loi empirique, ce qui ne constitut pas une preuve mathématique, sur les types d’entiers N qui donne une matrice diabolique par le procédé des cavaliers : les entiers premiers complétés des nombres s’écrivant 5*p où p est un nombre premier en partant de 5. Le menu : (programme.m) Le menu est conçu pour n’être quitter qu’en appuyant sur l’onglet Quitter ou en fermant la fenêtre du menu grâce à l’utilisation du drapeau. Les différents menus et sous menus sont arrangés ainsi : Les nombres premiers : - Le crible d’Erathostène. - La méthode par division. Les matrices magiques ou diaboliques : - Les matrices diaboliques. - Les matrices magiques. Quitter. Le code correspondant est : %--Affiche un menu pour traiter les nombres premiers et % les matrices magiques et diaboliques-%--Initialisation-- drapeau=0; %-----------------%--Menus-while ~drapeau k=menu('Voulez vous traitez sur...','...les nombres premiers','...les matrices magiques et diaboliques','Quitter'); if k==1 l=menu('Quel type d algorithme ? ','Crible Eratostene','methode par division'); if l==1 n=input('Rentrez la valeur de n : '); crible(n) else n=input('Rentrez la valeur de n : '); np(n) end elseif k==2 l=menu('Travailler sur les matrices...','...diaboliques','...magiques'); if l==1 m=menu('Voulez vous','tester une matrice','ou creer une matrice'); if m==1 A=input('Rentrez la matrice : '); if booleendiab(A) ** disp('A est diabolique'); ** else ** disp('A non diabolique'); ** end ** else n=input('Rentrez la dimension de la matrice : '); i=input('Rentrez la ligne de depart : '); j=input('Rentrez la colonne de depart : '); A=diabolic(n,i,j) end else m=menu('Voulez vous','tester une matrice','ou creer une matrice'); if m==1 A=input('Rentrez la matrice : '); if booleenmagic(A) ** disp('A est magique'); ** else ** disp('A non magique'); ** end ** else n=input('Rentrez la dimension de la matrice : '); if mod(n,2)==0 ** disp('n doit etre impair'); ** else ** A=magic(n) ** end ** end end else drapeau=1; end end %--------- Conclusion : Par différents algorithmes nous avons crée des listes de nombres premiers et des matrices aux caractéristiques spéciales. Le premier point qui ressort est le fait que l’outil informatique est d’une grande aide en ce qui concerne l’orientation de la réflexion. Il permet de trouver des lois empiriques qui permettront de s’orienter correctement. (Voir Test sur la taille N : p7-9). En ce qui concerne les créations de liste de nombres premier, une première extension au travail effectuée serait d’écrire un algorithme permettant de vérifier si un nombre n est premier : soit en se servant des listes déjà établies soit en se servant d’autres critères comme la divisibilité par tous les nombres premiers inférieurs à la racine de n. L’étude pourrait ensuite porter sur le temps de calcul d’un tel algorithme et la comparaison à d’autres. L’utilisation de la fonction error ne permet pas une bonne utilisation du menu. Cette fonction sort de la fonction appelée, affiche un message d’erreur et sort de programme.m ce qui est en contradiction avec l’utilisation d’un menu qui a pour but de se fermer seulement sur demande de l’utilisateur et non au résultat négatif d’un test. Le code correspondant est : >> programme Rentrez la dimension de la matrice : 6 ??? Error using ==> magic n pas impaire Error in ==> programme at 43 A=magic(n) Nous avons donc modifier le programme : rajout de tests if et utilisation de booleendiab au lieu de testdiabolic et booleenmagic au lieu de testmagic. (Voir les modification au niveau de ** dans le menu).