Implémentation de la version Creuse, création de H encore trop lente

git-svn-id: http://cregut.svn.enseeiht.fr/2020/1sn/pim/projets/GH-05@210314 e13453a9-b01f-0410-a051-f404c4f0c485
This commit is contained in:
lfainsin 2020-12-22 13:26:25 +00:00
parent a88dff28eb
commit 0cc449919d
9 changed files with 267 additions and 179 deletions

View file

@ -6,3 +6,5 @@ clean:
cd build/ && \
gnat clean ../src/*.adb
test:
bash test_pagerank.bash

View file

@ -1,45 +1,19 @@
% Utilisation du dépôt SVN pour le projet
%
%
**Remarque :** On peut engendrer une version pdf de ce fichier en faisant :
# Building
~~~
pandoc -N -o LISEZ-MOI.pdf LISEZ-MOI.txt
$ colormake
~~~
# Recommandation
# Cleaning
~~~
$ make clean
~~~
## Ne pas encombrer le serveur SVN avec des fichiers inutiles
# Testing
~~~
$ make test
~~~
**Ne pas pousser sur SVN les gros exemples.**
Vous pouvez les avoir dans votre copie locale mais il ne faut pas les mettre
sur SVN car vous n'avez pas à les modifier, qu'on peut les retrouver
facilement sur Moodle et qu'ils vont inutilement occuper beaucoup de place sur
le serveurs SVN. Il y a pas loin de 100 équipes !.
De la même façon, on ne met pas les exécutables ni aucun fichier résultat de
la compilation.
Si vous le faites, outre la place gaspillée sur le serveur, vous allez avoir
de nombreux conflits car SVN ne saura pas faire la fusion des fichiers objets
ou exécutables !
## Pousser régulièrement vos modifications
Vous devez pousser régulièrement vos modifications. Définissez de petits
objectifs (écrire un sous-programme, tester un sous-programme, améliorer un
algorithmique, etc.) et dès qu'il est atteint vous pousser vos modifications
sur le serveurs SVN.
Faites aussi des `svn update` régulièrement pour limiter les conflits et
communiquez avec votre coéquipier !
# Organisation du dépôt SVN
# Tree
. \
├── build \
@ -48,15 +22,22 @@ communiquez avec votre coéquipier !
│ ├── raffinages.txt \
│ └── rapport.pdf \
├── Makefile \
├── README.md \
└── src \
├── google_naive.adb \
├── google_naive.ads \
├── pagerank.adb \
├── vector.adb \
└── vector.ads \
├── README.md \
├── src \
│ ├── google_creux.adb \
│ ├── google_creux.ads \
│ ├── google_naive.adb \
│ ├── google_naive.ads \
│ ├── pagerank.adb \
│ ├── vector.adb \
│ └── vector.ads \
└── test_pagerank.bash \
# Autres informations
# TODO
Vous pouvez ajouter ici toute information utile pour comprendre
l'organisation de votre dépôt...
- algo tri quicksort
- implémenter creux
- paufinner tests
- rédiger rapport
- rédiger présentation
- meilleur initialize(vec)

View file

@ -1,72 +1,70 @@
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Text_Streams;
package body Google_Creux is
function "*"(left : T_Vecteur; right : T_Google) return T_Vecteur is
vec: T_Vecteur;
c: T_Element;
-- construction simple, de compléxité N^2
-- on peut diminuer la compléxité en triant d'abord le réseau
-- on passerait à une complexité 2*N + N*Log(2, N)
procedure create_H(mat: in out T_Google; file: in out Ada.Text_IO.File_Type) is
row, col: Natural;
nb: Natural := 0;
begin
initialize(vec);
mat.rows(0) := 0;
for i in 0..N-1 loop
c := 0.0;
for j in 0..N-1 loop
c := c + left(j)*right(j,i);
reset(file, In_File);
skip_line(file);
for j in 0..N_links-1 loop
get(file, row);
get(file, col);
if row = i then
mat.cols(nb) := col;
nb := nb + 1;
end if;
end loop;
vec(i) := c;
end loop;
return vec;
end "*";
procedure create_H(mat: in out T_Google; file: in Ada.Text_IO.File_Type) is
row, col: Integer;
begin
while not end_of_File(file) loop
get(file, row);
get(file, col);
mat(row, col) := 1.0;
mat.rows(i+1) := nb;
end loop;
end create_H;
procedure create_S(mat: in out T_Google) is
sum: T_Element;
begin
for i in 0..N-1 loop
sum := 0.0;
for j in 0..N-1 loop
sum := sum + mat(i,j);
end loop;
if sum /= 0.0 then
for j in 0..N-1 loop
if mat(i,j) /= 0.0 then
mat(i,j) := 1.0/sum;
end if;
end loop;
else -- sum == 0 then
for j in 0..N-1 loop
mat(i,j) := 1.0/T_Element(N);
end loop;
end if;
end loop;
end create_S;
procedure create_G(mat: in out T_Google; alpha: in T_Element) is
begin
for i in 0..N-1 loop
for j in 0..N-1 loop
mat(i,j) := alpha*mat(i,j) + (1.0-alpha)/T_Element(N);
end loop;
end loop;
end create_G;
procedure put(mat: in T_Google) is
begin
for i in 0..N-1 loop
for j in 0..N-1 loop
put(mat(i,j));
end loop;
new_line;
for i in 0..N_links-1 loop
put(mat.cols(i));
end loop;
new_line;
for i in 0..N loop
put(mat.rows(i));
end loop;
end put;
function calcul(vec: in T_Vecteur_Element; mat: in T_Google; alpha: in T_Element) return T_Vecteur_Element is
new_vec: T_Vecteur_Element;
nb_col: Natural := 0;
col_CRS: Natural := 0;
col_vec: Natural := 0;
begin
initialize(new_vec, sum(vec)*(1.0-alpha)/T_Element(N));
for i in 0..N-1 loop
nb_col := mat.rows(i+1) - mat.rows(i);
if nb_col = 0 then
for j in 0..N-1 loop
new_vec(j) := new_vec(j) + alpha*vec(i)/T_Element(N);
end loop;
else
for j in 1..nb_col loop
col_vec := mat.cols(col_CRS);
new_vec(col_vec) := new_vec(col_vec) + alpha*vec(i)/T_Element(nb_col);
col_CRS := col_CRS + 1;
end loop;
end if;
end loop;
return new_vec;
end calcul;
end Google_Creux;

View file

@ -5,6 +5,7 @@ generic
type T_Element is digits <>;
N: Positive;
N_links: Positive;
with package Vector_T_Element is new Vector(T_Element => T_Element, N => N);
package Google_Creux is
@ -17,13 +18,17 @@ package Google_Creux is
-- on utilise le module Vector
use Vector_T_Element;
type T_Google is array (0..N-1, 0..N-1) of T_Element;
type T_Rows is array (0..N) of Natural;
type T_Cols is array (0..N_links-1) of Natural;
type T_Google is record
cols: T_Cols;
rows: T_Rows;
offset: T_Element;
end record;
function "*"(left: T_Vecteur; right: T_Google) return T_Vecteur;
function calcul(vec : T_Vecteur_Element; mat : T_Google; alpha: in T_Element) return T_Vecteur_Element;
procedure create_H(mat: in out T_Google; file: in Ada.Text_IO.File_Type);
procedure create_S(mat: in out T_Google);
procedure create_G(mat: in out T_Google; alpha: in T_Element);
procedure create_H(mat: in out T_Google; file: in out Ada.Text_IO.File_Type);
procedure put(mat: in T_Google);

View file

@ -2,11 +2,11 @@ with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
package body Google_Naive is
function "*"(left : T_Vecteur; right : T_Google) return T_Vecteur is
vec: T_Vecteur;
function "*"(left : T_Vecteur_Element; right : T_Google) return T_Vecteur_Element is
vec: T_Vecteur_Element;
c: T_Element;
begin
initialize(vec);
initialize(vec); -- garder ?
for i in 0..N-1 loop
c := 0.0;
for j in 0..N-1 loop

View file

@ -19,7 +19,7 @@ package Google_Naive is
type T_Google is array (0..N-1, 0..N-1) of T_Element;
function "*"(left: T_Vecteur; right: T_Google) return T_Vecteur;
function "*"(left: T_Vecteur_Element; right: T_Google) return T_Vecteur_Element;
procedure initialize(mat: in out T_Google);

View file

@ -2,6 +2,7 @@ with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Text_Streams;
with Vector;
with Google_Naive;
@ -10,9 +11,13 @@ with Google_Creux;
procedure pageRank is
ERROR_args: Exception;
ERROR_alpha: Exception;
ERROR_ite: Exception;
ERROR_unexpected: Exception;
INFO_help: Exception;
-- définition du type T_Double
Type T_Double is digits 11;
Type T_Double is digits 18;
-- on utilise le module générique Float_IO pour pouvoir afficher T_Double directement
package Text_T_Double is
new Ada.Text_IO.Float_IO(Num => T_Double);
@ -21,7 +26,8 @@ procedure pageRank is
-- proédure pour récupérer les arguments de la ligne de commande
-- procédure pour récupérer les arguments de la ligne de commande
procedure get_args(filename: in out Unbounded_String;
ite_max: in out Natural;
alpha: in out T_Double;
@ -41,22 +47,32 @@ procedure pageRank is
new_line;
-- on vérifie d'abord que le nombre d'arguments est cohérent
if not(0 < Argument_Count and Argument_Count <= 6) then
if not(0 < Argument_Count and Argument_Count <= 7) then
raise ERROR_args;
else -- sinon on parse les arguments
loop
if Argument(i) = "-P" then
if Argument(i) = "-h" or Argument(i) = "--help" then
put_line("parsed help");
raise INFO_help;
elsif Argument(i) = "-n" or Argument(i) = "--naif" then
naif := True;
i := i + 1;
put_line("parsed naif");
elsif Argument(i) = "-A" then
elsif Argument(i) = "-a" or Argument(i) = "--alpha" then
alpha := T_Double'Value(Argument(i+1));
if alpha < 0.0 or alpha > 1.0 then
raise ERROR_alpha;
end if;
i := i + 2;
put_line("parsed alpha");
elsif Argument(i) = "-I" then
elsif Argument(i) = "-i" or Argument(i) = "--ite-max" then
ite_max := Natural'Value(Argument(i+1));
if ite_max > 150 then
raise ERROR_ite;
end if;
i := i + 2;
put_line("parsed ite_max");
@ -66,8 +82,12 @@ procedure pageRank is
put_line("parsed filename");
else
put_line("unexpected passing case");
raise ERROR_args;
new_line;
put("Option: '");
put(Argument(i));
put("' non reconnu");
new_line;
raise ERROR_unexpected;
end if;
exit when i > Argument_Count;
@ -75,38 +95,50 @@ procedure pageRank is
end if;
new_line;
put("alpha = "); put(alpha, 1); new_line;
put("alpha = "); put(alpha, Fore=>1, Aft=>10); new_line;
put("naif = "); put(Boolean'Pos(naif), 1); new_line;
put("ite_max = "); put(ite_max, 1); new_line;
put("filename = "); put_line(To_String(filename));
new_line;
exception
when others => raise ERROR_args;
when CONSTRAINT_ERROR =>
if Argument(i) = "-a" or Argument(i) = "--alpha" then
raise ERROR_alpha;
elsif Argument(i) = "-i" or Argument(i) = "--ite-max" then
raise ERROR_ite;
end if;
end get_args;
-- procédure pour choisir le type d'algo, une fois N et les arguments récupérés
procedure type_algo(N: Natural;
procedure type_algo(N: Positive;
N_links: Positive;
filename: in Unbounded_String;
file: in out Ada.Text_IO.File_Type;
alpha: T_Double;
ite_max: Natural;
naif: Boolean) is
-- on instancie le module générique Vecteur
package Vector_T_Double is
new Vector(T_Element => T_Double,
N => N);
use Vector_T_Double;
-- pour le retour chariot
stdout: constant Ada.Text_IO.File_Type := Ada.Text_IO.Standard_Output;
-- procédure qui effectue l'algorithme du pageRank avec Google_Naive
procedure algorithm_naif(file: in out Ada.Text_IO.File_Type;
alpha: in T_Double;
ite_max: in Natural;
pi: out T_Vecteur) is
pi: out T_Vecteur_Element) is
-- on instancie le module générique Naif de Google
package Google is
@ -122,57 +154,75 @@ procedure pageRank is
initialize(pi);
put_line("initialized pi");
--put(pi); new_line;
-- put(pi); new_line;
initialize(G);
put_line("initialized G");
--put(G); new_line;
-- put(G); new_line;
create_H(G, file);
put_line("created H");
close(file);
--put(G); new_line;
-- put(G); new_line;
create_S(G);
put_line("created S");
--put(G); new_line;
-- put(G); new_line;
create_G(G, alpha);
put_line("created G");
--put(G); new_line;
-- put(G); new_line;
-- on applique l'algorithme itératif
put("ite: ");
for i in 1..ite_max loop
pi := pi * G;
put(i, 1); put(" ");
String'Write(Ada.Text_IO.Text_Streams.Stream(stdout),
"ite:" & Integer'Image(i) & " /" & Integer'Image(ite_max) & ASCII.CR);
end loop; new_line;
--new_line;
--put_line("final pi:");
--put(pi);
new_line;
put_line("final pi:");
put(pi);
end algorithm_naif;
-- procédure qui effectue l'algorithme du pageRank avec Google_Creux
procedure algorithm_creux(file: in out Ada.Text_IO.File_Type;
alpha: in T_Double;
ite_max: in Natural;
pi: out T_Vecteur) is
alpha: in T_Double;
ite_max: in Natural;
pi: out T_Vecteur_Element) is
-- on instancie le module générique Creux de Google
package Google is
new Google_Creux(T_Element => T_Double,
N => N,
N_links => N_links,
Vector_T_Element => Vector_T_Double);
use Google;
-- définition de la matrice Google
G: T_Google;
H: T_Google;
begin
put("TODO");
initialize(pi);
put_line("initialized pi:");
-- put(pi); new_line;
create_H(H, file);
put_line("created H:");
-- put(H); new_line; new_line;
-- on applique l'algorithme itératif
for i in 1..ite_max loop
pi := calcul(pi, H, alpha);
String'Write(Ada.Text_IO.Text_Streams.Stream(stdout),
ASCII.CR & "ite:" & Integer'Image(i) & " /" & Integer'Image(ite_max));
end loop; new_line;
new_line;
put_line("final pi:");
put(pi);
end algorithm_creux;
@ -182,21 +232,20 @@ procedure pageRank is
-- procédure pour écrire les résultats dans les fichiers
procedure write_to_files(filename: in Unbounded_String;
pi_sorted: in T_Vecteur;
pi_index: in T_Vecteur_Index) is
pi_sorted: in T_Vecteur_Element;
pi_index: in T_Vecteur_Natural) is
file: Ada.Text_IO.File_Type;
begin
create(file, Out_File, To_String(filename & ".p"));
put(file, N, 1);
put(file, alpha, 2);
put(file, ite_max, 2);
new_line(file);
create(file, Out_File, To_String(filename & "_GH05.p"));
put(file, N, 1); put(file, ' ');
put(file, alpha, Fore=>1, Aft=>10); put(file, ' ');
put(file, ite_max, 1); new_line(file);
put(file, pi_sorted);
close(file);
create(file, Out_File, To_String(filename & ".ord"));
create(file, Out_File, To_String(filename & "_GH05.ord"));
put(file, pi_index);
close(file);
end write_to_files;
@ -206,8 +255,8 @@ procedure pageRank is
-- définition des vecteurs
pi: T_Vecteur;
pi_index: T_Vecteur_Index;
pi: T_Vecteur_Element;
pi_index: T_Vecteur_Natural;
begin
@ -221,9 +270,9 @@ procedure pageRank is
initialize(pi_index);
sort_with_index_desc(pi, pi_index);
new_line;
put_line("sorted pi:");
put(pi); new_line;
-- new_line;
-- put_line("sorted pi:");
-- put(pi); new_line;
-- on écrit les resultats dans des fichiers
write_to_files(filename, pi, pi_index);
@ -242,6 +291,7 @@ procedure pageRank is
-- définition des variables pour créer les matices/vecteurs
N: Positive;
N_links: Integer := -1;
file: Ada.Text_IO.File_Type;
begin
@ -254,18 +304,51 @@ begin
open(file, In_File, To_String(filename & ".net"));
put_line("file OK");
-- on récupère le nombre de liens
while not End_Of_File(file) loop
Skip_Line(file);
N_links := N_links + 1;
end loop;
reset(file, In_File);
put("N_links = "); put(N_links, 1); new_line;
-- on récupère le nombre de pages
get(file, N);
put("N = "); put(N, 1); new_line;
-- on peut maintenant choisir le type de matrice que l'on souhaite
type_algo(N, filename, file, alpha, ite_max, naif);
type_algo(N, N_links, filename, file, alpha, ite_max, naif);
exception
-- si il y a une erreur lors du parsing des arguments, on rappelle l'usage.
when ERROR_args =>
put_line("Erreur lors de la saisi de la commande");
put_line("Usage: pagerank [-I max_iterations] [-A alpha] [-P] fichier_reseau.net");
new_line;
put_line("Erreur lors de la saisi de la commande.");
put_line("Usage: pagerank [-P] [-i max_iterations] [-a alpha] [-h] fichier_reseau.net");
when ERROR_unexpected =>
put_line("Essayez 'pagerank --help' pour plus d'informations.");
when ERROR_alpha =>
new_line;
put_line("Erreur lors de la saisi de alpha.");
put_line("alpha ∈ [0, 1]");
when ERROR_ite =>
new_line;
put_line("Erreur lors de la saisi de ite_max.");
put_line("ite_max ∈ ⟦0, 150⟧");
when INFO_help =>
new_line;
put_line("Usage: pagerank [OPTIONS] network.net");
put_line("Calcule le pagerank d'un réseau à partir de son réseau.net");
new_line;
put_line("Options:");
put_line(" -P, --naif specifies which type of matrix to use");
put_line(" -a, --alpha specifies the alpha constant (alpha ∈ [0, 1])");
put_line(" -i, --ite-max specifies the maximum number of iterations (ite_max ∈ ⟦0, 150⟧)");
put_line(" -h, --help display this help message and exit");
end pageRank;

View file

@ -2,28 +2,52 @@ with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
package body vector is
procedure initialize(vec: in out T_Vecteur) is
procedure initialize(vec: in out T_Vecteur_Element) is
begin
for i in 0..N-1 loop
vec(i) := 1.0/T_Element(N);
end loop;
end initialize;
procedure initialize(vec: in out T_Vecteur_Index) is
procedure initialize(vec: in out T_Vecteur_Element; value: in T_Element) is
begin
for i in 0..N-1 loop
vec(i) := value;
end loop;
end initialize;
procedure initialize(vec: in out T_Vecteur_Natural) is
begin
for i in 0..N-1 loop
vec(i) := i;
end loop;
end initialize;
procedure put(vec: in T_Vecteur) is
function sum(vec: in T_Vecteur_Element) return T_Element is
s: T_Element := 0.0;
begin
for i in 0..N-1 loop
s := s + vec(i);
end loop;
return s;
end sum;
procedure put(vec: in T_Vecteur_Element) is
begin
for i in 0..N-1 loop
put(vec(i)); new_line;
end loop;
end put;
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur) is
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur_Element) is
begin
for i in 0..N-1 loop
put(file, vec(i), Fore=>1, Aft=>10);
new_line(file);
end loop;
end put;
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur_Natural) is
begin
for i in 0..N-1 loop
put(file, vec(i), 1);
@ -31,15 +55,7 @@ package body vector is
end loop;
end put;
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur_Index) is
begin
for i in 0..N-1 loop
put(file, vec(i), 1);
new_line(file);
end loop;
end put;
procedure sort_with_index_desc(vec: in out T_Vecteur; vec_index: in out T_Vecteur_Index) is
procedure sort_with_index_desc(vec: in out T_Vecteur_Element; vec_index: in out T_Vecteur_Natural) is
tmp_Element: T_Element;
tmp_Natural: Natural;
max: Natural;
@ -47,7 +63,7 @@ package body vector is
for i in 0..N-2 loop
max := i;
for j in i+1..N-1 loop
if vec(max) < vec(j) then
if vec(max) <= vec(j) then
max := j;
end if;
end loop;

View file

@ -7,21 +7,24 @@ generic
package Vector is
type T_Vecteur is array (0..N-1) of T_Element;
type T_Vecteur_Index is array (0..N-1) of Natural;
type T_Vecteur_Element is array (0..N-1) of T_Element;
type T_Vecteur_Natural is array (0..N-1) of Natural;
-- on permet l'affichage direct des T_Element
package Text_T_Element is
new Ada.Text_IO.Float_IO(Num => T_Element);
use Text_T_Element;
procedure initialize(vec: in out T_Vecteur);
procedure initialize(vec: in out T_Vecteur_Index);
procedure initialize(vec: in out T_Vecteur_Element);
procedure initialize(vec: in out T_Vecteur_Element; value: in T_Element);
procedure initialize(vec: in out T_Vecteur_Natural);
procedure put(vec: in T_Vecteur);
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur);
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur_Index);
function sum(vec: in T_Vecteur_Element) return T_Element;
procedure sort_with_index_desc(vec: in out T_Vecteur; vec_index: in out T_Vecteur_Index);
procedure put(vec: in T_Vecteur_Element);
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur_Element);
procedure put(file: in out Ada.Text_IO.File_Type; vec: in T_Vecteur_Natural);
procedure sort_with_index_desc(vec: in out T_Vecteur_Element; vec_index: in out T_Vecteur_Natural);
end Vector;