Recherche de nombres premiers.

publicité
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).
Téléchargement