Valid XHTML     Valid CSS2    

Listing du fichier progie8.php

 

00001     <?php
00002     #   # (gH)   -_-  progie8.php  ;  TimeStamp (unix) : 16 Février 2015 vers 21:27
00003     
00004     error_reporting
(E_ALL E_NOTICE E_STRICT) ;
00005     
00006     include_once("std7.php"
) ;
00007     include_once("progi.php"
) ;
00008     include_once("statuno7.php"
) ;
00009     
00010     $R 
s_span("R","gbleuf") ;
00011     $numSerie 
;
00012     debutPageExercices
($numSerie) ;
00013     
00014     ## -------------------------------------------------------------------------------------------
00015     
00016     p
("texte") ;
00017     echo "" 
;
00018     finp
() ;
00019     
00020     debutSection
() ;
00021     
00022     $tableauDesRubriques 
= array() ;
00023     $idr 
;
00024     
00025     $idr
++; $tableauDesRubriques[$idr] = "Code lisible et debug" ;
00026     $idr
++; $tableauDesRubriques[$idr] = "Optimisation" ;
00027     $idr
++; $tableauDesRubriques[$idr] = "Vitesses d'exécution" ;
00028     $idr
++; $tableauDesRubriques[$idr] = "Positions du maximum et gestion de la mémoire" ;
00029     $idr
++; $tableauDesRubriques[$idr] = "Tris et \"big data\"" ;
00030     
00031     $tdmCRLM 
= new tdm($tableauDesRubriques) ;
00032     $tdmCRLM
->titre() ;
00033     $tdmCRLM
->menu("oui","oui","nou") ;
00034     
00035     afficherSolutions
($numSerie) ;
00036     
00037     finSection
() ;
00038     
00039     debutSection
() ;
00040     $numExo 
;
00041     
00042     ## -------------------------------------------------------------------------------------------
00043     
00044     $tdmCRLM
->afficheRubrique("oui") ; $numExo++ ; # Code lisible et debug
00045     
00046     ## -------------------------------------------------------------------------------------------
00047     
00048     blockquote
() ;
00049     
00050     blockquote
() ;
00051     
00052     p
("texte") ;
00053     echo "A-t-on besoin de la fonction  "
.hrrr("debug")." pour trouver pourquoi le code suivant ne fonctionne pas, \n" ;
00054     echo "sachant qu'on cherche à renvoyer la chaine de caractères passée en paramètre \n" 
;
00055     echo "avec la lettre initiale en majuscule et toute le reste en minuscules&nbsp;? \n" 
;
00056     finp
() ;
00057     
00058     pre_fichier
("maju01.r","cadre") ;
00059     
00060     finblockquote
() ;
00061     
00062     solution
($numExo,$numSerie) ;
00063     
00064     p
("texte") ;
00065     echo "Sans doute que non. Ce code est mal écrit. \n" 
;
00066     echo "Vu qu'il y a une seule instruction dans le code proposé, \n" 
;
00067     echo ""
.noir("debug()")." ne peut rien pour nous. Démonstration&nbsp;: \n" ;
00068     finp
() ;
00069     
00070     pre_fichier
("maju01.txt","cadre") ;
00071     
00072     p
("texte") ;
00073     echo "Pour que le déboggage soit efficace, \n" 
;
00074     echo "il vaudrait mieux décomposer chacune \n" 
;
00075     echo "des actions, avec quelque chose comme \n" 
;
00076     finp
() ;
00077     
00078     pre_fichier
("maju02.r","cadre") ;
00079     
00080     p
("texte") ;
00081     echo "pour se rendre compte que les indices sont faux. \n" 
;
00082     echo "Avec le nouveau code proposé, on peut tester chaque appel de fonction séparément \n" 
;
00083     echo "et en déduire que la variable nommée "
.noir("initiale")." ne contient pas la bonne valeur, en \n" ;
00084     echo "utilisant cette fois "
.noir("debug()").". On peut alors corriger les indices pour ".noir("initiale")." \n" ;
00085     echo "et pour "
.noir("resteDeChaine")." qui étaient faux (mais qui ne généraient pas d'erreur)&nbsp;: \n" ;
00086     finp
() ;
00087     
00088     pre_fichier
("maju03.r","cadre") ;
00089     
00090     finsolution
() ;
00091     
00092     finblockquote
() ;
00093     
00094     ## -------------------------------------------------------------------------------------------
00095     
00096     $tdmCRLM
->afficheRubrique("oui") ; $numExo++ ; # Optimisation
00097     
00098     ## -------------------------------------------------------------------------------------------
00099     
00100     blockquote
() ;
00101     
00102     blockquote
() ;
00103     
00104     p
("texte") ;
00105     echo "On dispose d'une fonction mathématique  "
.noir("f")." et on voudrait calculer sa valeur \n" ;
00106     echo "en "
.noir("n")." points répartis uniformément sur l'intervalle ".noir("[a,b]")." à l'aide d'une boucle. \n" ;
00107     echo "On propose la formule suivante pour \n" 
;
00108     echo "calculer la position de chacun des points "
.noir("x".sub("i")).", pour ".noir("i")." de 1 à ".noir("n").", " ;
00109     echo " sachant que "
.noir("x".sub("1"))."=".noir("a")." et ".noir("x".sub("n"))."=".noir("b")."&nbsp;: \n" ;
00110     finp
() ;
00111     
00112     #%
00113     #$$x_i = a + (b-a)\times \frac{(i-1)}{(n-1)}$$
00114     #%
00115     
00116     $img 
"formule.png" ;
00117     p
() ;
00118     nbsp
(20) ;
00119     echo href
($img,img($img,"",300)) ;
00120     finp
() ;
00121     
00122     p
("texte") ;
00123     echo "On veut par exemple tester ce calcul avec "
.noir("f(x)=x+1")." sur l'intervalle ".noir("[0,1]")." \n" ;
00124     echo "avec "
.noir("n=100")." points. \n" ;
00125     finp
() ;
00126     
00127     p
("texte") ;
00128     echo "Quel serait le code optimisé pour cette boucle ? \n" 
;
00129     finp
() ;
00130     
00131     p
("texte") ;
00132     echo "Peut-on effectuer le calcul sans boucle ? \n" 
;
00133     finp
() ;
00134     
00135     finblockquote
() ;
00136     
00137     solution
($numExo,$numSerie) ;
00138     
00139     p
("texte") ;
00140     echo "La formule fournie pour calculer chacun des "
.noir("x".sub("i"))." est tout à fait correcte mathématiquement. \n" ;
00141     echo "Sa programmation na&iuml;ve ne pose aucun problème&nbsp;: \n" 
;
00142     finp
() ;
00143     
00144     pre_fichier
("xi01.r","cadre") ;
00145     
00146     p
("texte") ;
00147     echo "Une première optimisation de la boucle consiste à sortir les \"constantes\" de la boucle \n" 
;
00148     echo "et à initialiser le vecteur de sortie, soit le code&nbsp;: \n" 
;
00149     finp
() ;
00150     
00151     pre_fichier
("xi02.r","cadre") ;
00152     
00153     p
("texte") ;
00154     echo "Une deuxième optimisation consiste à remarquer que les "
.noir("x".sub("i"))." sont en progression arithmétique, \n" ;
00155     echo "donc il suffit de rajouter le pas "
.noir("h")." de la progression pour passer d'un point à l'autre&nbsp;: \n" ;
00156     finp
() ;
00157     
00158     pre_fichier
("xi03.r","cadre") ;
00159     
00160     p
("texte") ;
00161     echo "Bien sûr le calcul vectoriel permet de se passer de boucle&nbsp;: \n" 
;
00162     finp
() ;
00163     
00164     pre_fichier
("xi04.r","cadre") ;
00165     
00166     p
("texte") ;
00167     echo "Et enfin, on peut se demander si la fonction  "
.hrrr("seq")." ne pourrait pas suffire&nbsp;: \n" ;
00168     finp
() ;
00169     
00170     pre_fichier
("xi05.r","cadre") ;
00171     
00172     p
("texte") ;
00173     echo "Le jeu en vaut-il la chandelle ? Vérifions-le avec la fonction  "
.noir("microbenchmark()")."&nbsp;: \n" ;
00174     finp
() ;
00175     
00176     pre_fichier
("xiperf.txt","cadre") ;
00177     
00178     p
("texte") ;
00179     echo "Le résultat est sans appel&nbsp;: la solution 4, basée sur "
.noir("1:n")." est de loin la plus performante, \n" ;
00180     echo "puisqu'elle est près de 40 fois plus rapide que la solution na&iuml;ve, en moyenne comme en médiane. \n" 
;
00181     echo "La solution 5 qui utilise la fonction  "
.noir("seq()")." \n" ;
00182     echo "n'est sans doute pas adaptée ici, même si elle est assez rapide. \n" 
;
00183     finp
() ;
00184     
00185     p
("texte") ;
00186     echo "Peut-on encore optimiser ?  Oui, sans doute, mais à condition de tester des cas particuliers. \n" 
;
00187     echo "Par exemple, on peut remarquer que si "
.noir("a")." est égal à 0 alors il n'y pas d'addition à faire. \n" ;
00188     echo "De même, si "
.noir("f")." est une fonction constante, on n'a pas besoin de calculer les ".noir("x".sub("i"))." \n" ;
00189     finp
() ;
00190     
00191     p
("texte") ;
00192     echo "Au passage, vous pourriez vous demander pourquoi nous n'avons pas mis le calcul des "
.noir("f(x".sub("i").")")." dans \n" ;
00193     echo "les fonctions. La réponse est simple&nbsp;: ce qu'on doit comparer est la génération des  "
.noir("x".sub("i")).". \n" ;
00194     echo "Après avoir vérifié que les fonctions renvoient les mêmes \n" 
;
00195     echo "vecteurs, \n" 
;
00196     echo "les calculs des "
.noir("f(x".sub("i").")")." prendront autant de temps. Les inclure dans les fonctions ajouterait \n" ;
00197     echo "les durées de calcul des "
.noir("f(x".sub("i").")")." qui peuvent être beaucoup plus importantes que celles des générations des ".noir("x".sub("i"))."\n" ;
00198     echo "et masquer ainsi les durées de génération. \n" 
;
00199     finp
() ;
00200     
00201     p
("texte") ;
00202     echo "Vous vous rappelez sans doute comment tester que deux vecteurs sont égaux, mais voici quand même \n" 
;
00203     echo "ce qu'il faut écrire et ce qu'il ne faut pas écrire pour le tester&nbsp;: \n" 
;
00204     finp
() ;
00205     
00206     pre_fichier
("xiegaux.r","cadre") ;
00207     
00208     pre_fichier
("compxi.sor","cadrejaune") ;
00209     
00210     finsolution
() ;
00211     
00212     finblockquote
() ;
00213     
00214     ## -------------------------------------------------------------------------------------------
00215     
00216     $tdmCRLM
->afficheRubrique("oui") ; $numExo++ ; # Vitesses d'exécution
00217     
00218     ## -------------------------------------------------------------------------------------------
00219     
00220     blockquote
() ;
00221     
00222     blockquote
() ;
00223     
00224     p
("texte") ;
00225     echo "Peut-on vraiment affirmer que le code "
.noir("mot %in% vec")." est vraiment plus \n" ;
00226     echo "rapide que le code "
.noir("grep(mot,vec)")."&nbsp;? \n" ;
00227     finp
() ;
00228     
00229     p
("texte") ;
00230     echo "Et que "
.noir("any(v&gt;0)")." est vraiment plus \n" ;
00231     echo "rapide que le code "
.noir("sum(v&gt;0)&gt;0")."&nbsp;? \n" ;
00232     finp
() ;
00233     
00234     p
("texte") ;
00235     echo "Faut-il \"sortir\" les calculs dans les écritures des bornes des boucles&nbsp;? Ainsi, \n" 
;
00236     echo "faut-il écrire les boucles "
.bleu("POUR")." et ".bleu("TANT QUE")." sous la forme \n" ;
00237     finp
() ;
00238     
00239     pre_fichier
("sortir1.txt","cadre") ;
00240     
00241     p
("texte") ;
00242     echo "plutôt que de les écrire \n" 
;
00243     finp
() ;
00244     
00245     pre_fichier
("sortir2.txt","cadre") ;
00246     
00247     p
("texte") ;
00248     echo "Peut-on encore optimiser le code suivant qui calcule le \n" 
;
00249     echo "maximum d'un vecteur, son nombre d'occurrences et toutes ses positions&nbsp;? \n" 
;
00250     finp
() ;
00251     
00252     pre_fichier
("max08.r","cadre") ;
00253     
00254     p
("texte") ;
00255     echo " Que faire si finalement 
$R est lent, non dans les fonctions de base mais dans une " ;
00256     echo " fonction utilisateur&nbsp;?" 
;
00257     finp
() ;
00258     
00259     
00260     finblockquote
() ;
00261     
00262     solution
($numExo,$numSerie) ;
00263     
00264     p
("texte") ;
00265     echo "Il est certainement difficile de démontrer mathématiquement qu'une expression \n" 
;
00266     echo "s'exécute vraiment plus rapidement qu'une autre, sauf à être capable de calculer \n" 
;
00267     echo "la complexité des algorithmes sous-jacents. Par contre, avec suffisamment \n" 
;
00268     echo "d'exemples, on doit pouvoir se convaincre de la rapidité de tel ou tel code. \n" 
;
00269     finp
() ;
00270     
00271     p
("texte") ;
00272     echo "En ce qui concerne la détection de la présence d'un mot dans une liste, il semblerait bien que \n" 
;
00273     echo "l'expression "
.noir("mot %in% vec")." est vraiment plus \n" ;
00274     echo "rapide que le code "
.noir("grep(mot,vec)").", même si ajouter le paramètre ".noir("fixed=TRUE")." \n" ;
00275     echo "diminue très sensiblement la durée d'exécution. Pour mémoire, mettre "
.noir("fixed=TRUE")." \n" ;
00276     echo "comme paramètre dans l'appel de "
.noir("grep")." prévient $R qu'on cherche une chaine \n" ;
00277     echo "de caractères et non pas une expression régulière, ce qui est plus simple \n" 
;
00278     echo "à réaliser et donc plus rapide à exécuter&nbsp;: \n" 
;
00279     finp
() ;
00280     
00281     pre_fichier
("vite1.txt","cadre") ;
00282     
00283     p
("texte") ;
00284     echo "En ce qui concerne la deuxième question sur la présence d'au moins un élément positif dans un vecteur, \n" 
;
00285     echo "le code suivant qui utilise trois expressions vectorielles donne des résultats d'exécution différents suivant la position \n" 
;
00286     echo "des valeurs positives dans le vecteur&nbsp;: \n" 
;
00287     finp
() ;
00288     
00289     pre_fichier
("vite2a.txt","cadre") ;
00290     
00291     p
("texte") ;
00292     echo "Par exemple, avec deux cas extrêmes où la seule valeur positive est située en début ou en fin d'un vecteur de 100&nbsp;000 éléments, \n" 
;
00293     echo "ce n'est pas la même expression vectorielle qui est plus efficace&nbsp;: \n" 
;
00294     finp
() ;
00295     
00296     pre_fichier
("vite2b.txt","cadre") ;
00297     
00298     p
("texte") ;
00299     echo "On pourrait penser écrire notre propre boucle tant que de détection du premier élément positif dans le vecteur, \n" 
;
00300     echo "comme dans le code suivant&nbsp;: \n" 
;
00301     finp
() ;
00302     
00303     pre_fichier
("vite3.r","cadre") ;
00304     
00305     p
("texte") ;
00306     echo "Pour nos cas extrêmes, les résultats sont extrêmes aussi&nbsp;: \n" 
;
00307     finp
() ;
00308     
00309     pre_fichier
("vite4.txt","cadre") ;
00310     
00311     p
("texte") ;
00312     echo "Il faut donc en retenir qu'optimiser du code suppose parfois qu'on connait ou qu'on est capable de \"deviner\" la distribution \n" 
;
00313     echo "des données, ce qui n'est pas une mince affaire. \n" 
;
00314     finp
() ;
00315     
00316     p
("texte") ;
00317     echo "La réponse à la troisième question concernant les conditions de sortie de boucle est un peu plus simple&nbsp;: il faut mettre les \n" 
;
00318     echo "calculs constants à l'extérieur des boucles. Il faut donc prendre l'habitude d'écrire \n" 
;
00319     finp
() ;
00320     
00321     pre_fichier
("vite5a.r","cadre") ;
00322     
00323     p
("texte") ;
00324     echo "plutôt que \n" 
;
00325     finp
() ;
00326     
00327     pre_fichier
("vite5b.r","cadre") ;
00328     
00329     p
("texte") ;
00330     echo "car même si le gain n'est pas très important, il est non négligeable, même sur cet exemple simple&nbsp;: \n" 
;
00331     finp
() ;
00332     
00333     pre_fichier
("vite5.txt","cadre") ;
00334     
00335     p
("texte") ;
00336     echo "Pour finir cet exercice, il est facile de voir qu'on peut encore optimiser le code proposé \n" 
;
00337     echo "puisque l'expression vectorielle "
.noir("V==maxV")." est utilisée deux fois et donc calculée deux fois. \n" ;
00338     finp
() ;
00339     
00340     p
("texte") ;
00341     echo "Si on ne calcule qu'une seule fois cette expression, \n" 
;
00342     echo "on dispose d'un code qui peut être jusqu'à deux fois plus rapide&nbsp;: \n" 
;
00343     finp
() ;
00344     
00345     pre_fichier
("max09.txt","cadre") ;
00346     
00347     p
("texte") ;
00348     echo " Si au final, après une étude de complexité de l'algorithme, " 
;
00349     echo 
$R est lent dans une de vos fonctions, une solution possible consiste à interfacer un programme C++ depuis $R ou, " ;
00350     echo " dans l'autre sens, appeler 
$R depuis un programme C++. Les packages " ;
00351     echo hrrp
("Rcpp") ;
00352     echo " et " 
;
00353     echo hrrp
("RInside") ;
00354     echo " sont prévus pour cela. On pourra consulter le site " 
;
00355     echo href
("http://www.rcpp.org/","rcpp.org") ;
00356     echo " et les livres suivants&nbsp;:" 
;
00357     finp
() ;
00358     
00359     p
() ;
00360     nbsp
(5) ;
00361     $img 
"retcpp.png" ;
00362     echo href
($img,img($img,"",800)) ;
00363     finp
() ;
00364     
00365     $urlTV  
"https://cran.r-project.org/web/views/" ;
00366     $urlHPC 
"https://cran.r-project.org/web/views/HighPerformanceComputing.html" ;
00367     $urlML  
"https://cran.r-project.org/web/views/MachineLearning.html" ;
00368     
00369     p
("texte") ;
00370     echo "Il ne faut pas oublier non plus que 
$R dispose, dans ses fameuses " ;
00371     echo href
($urlTV,em("Task Views")).", " ;
00372     echo " d'une entrée "
.href($urlHPC,"HPC") ;
00373     echo " et d'une entrée "
.href($urlML,"ML") ;
00374     echo "." 
;
00375     finp
() ;
00376     
00377     finsolution
() ;
00378     
00379     finblockquote
() ;
00380     
00381     ## -------------------------------------------------------------------------------------------
00382     
00383     $tdmCRLM
->afficheRubrique("oui") ; $numExo++ ; # Positions du maximum et gestion de la mémoire
00384     
00385     ## -------------------------------------------------------------------------------------------
00386     
00387     blockquote
() ;
00388     
00389     blockquote
() ;
00390     
00391     p
("texte") ;
00392     echo "On veut trouver les 5 premières positions du maximum dans un très grand vecteur d'entiers. \n" 
;
00393     echo "Est-ce un problème ? \n" 
;
00394     finp
() ;
00395     
00396     p
("texte") ;
00397     echo "Et si maintenant on veut stocker toutes les positions du maximum, comment faire \n" 
;
00398     echo "sachant qu'il peut y avoir potentiellement très peu de positions ou au contraire \n" 
;
00399     echo "un très grand nombre d'occurrences de ce maximum&nbsp;? \n" 
;
00400     finp
() ;
00401     
00402     finblockquote
() ;
00403     
00404     solution
($numExo,$numSerie) ;
00405     
00406     p
("texte") ;
00407     echo "Le mieux est sans doute de commencer par une solution na&iuml;ve et de tester sa \n" 
;
00408     echo "vitesse d'exécution, soit le code&nbsp;: \n" 
;
00409     finp
() ;
00410     
00411     pre_fichier
("5posmax01.r","cadre") ;
00412     
00413     p
("texte") ;
00414     echo "Si c'est effectivement trop lent, on peut envisager un parcours du vecteur \n" 
;
00415     echo "à l'aide d'une boucle tant que et sortir dès qu'on a trouvé les 5 premières positions du maximum&nbsp;: \n" 
;
00416     finp
() ;
00417     
00418     pre_fichier
("5posmax02.r","cadre") ;
00419     
00420     p
("texte") ;
00421     echo "Il est sans doute possible d'encore optimiser à l'aide de méta-connaissances. \n" 
;
00422     echo "Par exemple si on sait que le vecteur dans lequel dans on recherche le \n" 
;
00423     echo "maximum est issu d'une méthode qui converge vers des grandes valeurs, on pourrait \n" 
;
00424     echo "commencer la recherche par la fin en initialisant l'indice courant de recherche "
.noir("indc")." avec \n" ;
00425     echo "la longueur "
.noir("lngv")." du vecteur \n" ;
00426     echo "au lieu de  "
.noir("1")." \n" ;
00427     echo "et remonter vers le début du vecteur, donc en mettant  "
.noir("(indc>=1)")." \n" ;
00428     echo "comme deuxième test dans la condition de bouclage du TANT QUE \n" 
;
00429     echo "et en décrémentant "
.noir("indc")."&nbsp;: \n" ;
00430     finp
() ;
00431     
00432     pre_fichier
("5posmax03.txt","cadre") ;
00433     
00434     p
("texte") ;
00435     echo "Si au contraire on sait que la méthode est perturbée ou relativement stationnaire \n" 
;
00436     echo "au début et en fin, on pourrait commencer à partir du milieu du vecteur et parcourir \n" 
;
00437     echo "alternativement à gauche et à droite de cette position de départ, ou commencer \n" 
;
00438     echo "avec une position aléatoire \"pas trop proche\" des bords... \n" 
;
00439     finp
() ;
00440     
00441     p
("texte") ;
00442     echo "Une deuxième difficulté consiste à choisir des exemples pour tester la vitesse d'exécution des trois solutions \n" 
;
00443     echo "présentées. Ainsi, vaut-il mieux générer \n" 
;
00444     echo ""
.noir("leVecteur")." à l'aide de l'expression ".noir("round(runif(n=10**w,min=0,max=100))")." \n" ;
00445     echo "ou avec "
.noir("rbinom(n=10**w,size=50,prob=p)")."&nbsp;? Et avec quelle valeur de ".noir("w")." et ".noir("p")."&nbsp;? \n" ;
00446     echo "Serait-ce mieux d'utiliser une autre distribution, comment et pourquoi&nbsp;? \n" 
;
00447     finp
() ;
00448     
00449     p
("texte") ;
00450     echo "En ce qui concerne toutes les positions du maximum, le problème est un peu plus compliqué \n" 
;
00451     echo "puisqu'on ne connait pas la taille du résultat. On a déjà vu que concaténer une valeur à \n" 
;
00452     echo "un vecteur est très lent, en d'autres termes, il faut éviter d'écrire \n" 
;
00453     finp
() ;
00454     
00455     pre_fichier
("posmax01.r","cadre") ;
00456     
00457     p
("texte") ;
00458     echo "au profit d'une écriture en mémoire dans un vecteur de taille définie à l'avance soit \n" 
;
00459     finp
() ;
00460     
00461     pre_fichier
("posmax02.r","cadre") ;
00462     
00463     p
("texte") ;
00464     echo "Comme on ne peut pas prédire à l'avance la taille du résultat, si on doit absolument passer par une boucle "
.bleu("POUR").", \n" ;
00465     echo "l'optimisation consiste à ne PAS changer la taille du vecteur résultat TROP SOUVENT. \n" 
;
00466     echo "Donc au lieu de changer cette cette taille à chaque passage dans la boucle lorsqu'on trouve une nouvelle fois le maximum, \n" 
;
00467     echo "il faut astuctieusement changer cette taille "
.em("de temps en temps").", quand la taille courante ne suffit plus. \n" ;
00468     echo "Si (par sondage, expertise, test...) on connait en gros l'augmentation souhaitée de la taille, \n" 
;
00469     echo "on peut en profiter pour ne pas trop augmenter à chaque fois la taille ; \n" 
;
00470     echo "sinon on peut choisir de la doubler. Voici ce que cela donnerait sur exemple où nous avons décidé d'utiliser une \n" 
;
00471     echo "taille de "
.noir("n1 &lt;- 5")." éléments au départ et de rajouter ".noir("n2 &lt;- 7")." élements à chaque fois qu'il y en a besoin. \n" ;
00472     echo "Ces  valeurs sont ici arbitraires et ne servent qu'à la démonstration. De \"vraies\" valeurs seraient plutot de l'ordre de \n" 
;
00473     echo "d'une grande puissance de 10 puisqu'il faudrait déjà que l'expression vectorielle "
.noir("which(V==maxV)")." ne soit pas \n" ;
00474     echo "efficace... \n" 
;
00475     finp
() ;
00476     
00477     p
("texte") ;
00478     echo "Une remarque&nbsp;: si on augmente de temps en temps la taille du vecteur de résultats avec de "
.noir("NA").", il ne faut pas oublier \n" ;
00479     echo "de retirer à la fin ceux qui n'ont pas été remplacés par une vraie position du maximum. C'est bien sûr ce que nou avons \n" 
;
00480     echo "fait dans le code suivant&nbsp;: \n" 
;
00481     finp
() ;
00482     
00483     pre_fichier
("posmax03.r","cadre") ;
00484     
00485     p
("texte") ;
00486     echo "Voici ce qu'on obtient sur un exemple&nbsp;: \n" 
;
00487     finp
() ;
00488     
00489     pre_fichier
("posmax03.txt","cadre") ;
00490     
00491     finsolution
() ;
00492     
00493     finblockquote
() ;
00494     
00495     ## -------------------------------------------------------------------------------------------
00496     
00497     $tdmCRLM
->afficheRubrique("oui") ; $numExo++ ; # Tris et \"big data\"
00498     
00499     ## -------------------------------------------------------------------------------------------
00500     
00501     blockquote
() ;
00502     
00503     blockquote
() ;
00504     
00505     p
("texte") ;
00506     echo "On dispose d'un fichier issu de la bioinformatique dont la taille est \n" 
;
00507     echo "environ 4&nbsp;Go. \n" 
;
00508     finp
() ;
00509     
00510     p
("texte") ;
00511     echo "Comment faire pour trier les lignes de ce fichier sachant que \n" 
;
00512     echo "la mémoire de l'ordinateur est seulement de 2&nbsp;Go \n" 
;
00513     echo "et qu'on veut les cinq premières lignes triées&nbsp;? \n" 
;
00514     finp
() ;
00515     
00516     p
("texte") ;
00517     echo "En fait, on ne s'intéresse qu'aux cinq lignes les plus longues de ce fichier. \n" 
;
00518     echo "Faut-il le trier par ordre de taille de ligne et n'en garder que les cinq premières \n" 
;
00519     echo "lignes ou peut-on écrire un algorithme plus efficace&nbsp;? \n" 
;
00520     finp
() ;
00521     
00522     p
("texte") ;
00523     echo "Peut-on vraiment affirmer que le code "
.noir("sort(V,dec=TRUE)")." est vraiment plus \n" ;
00524     echo "rapide que le code "
.noir("rev(sort(V))")." pour trier par ordre décroissant&nbsp;? \n" ;
00525     finp
() ;
00526     
00527     finblockquote
() ;
00528     
00529     solution
($numExo,$numSerie) ;
00530     
00531     p
("texte") ;
00532     echo "Ah, la bioinformatique et ses gros fichiers&nbsp;! \n" 
;
00533     finp
() ;
00534     
00535     p
("texte") ;
00536     echo "On commence ici à entrer dans des problèmes plus délicats et c'est pourquoi ce sera \n" 
;
00537     echo "le dernier exercice de cette section. \n" 
;
00538     finp
() ;
00539     
00540     p
("texte") ;
00541     echo "Cet exercice peut être classé dans la catégorie "
.em("exercices de la mort qui tue")." car \n" ;
00542     echo "il est à la fois chronophage et \"prise de tête\". Voici par exemple ce qu'il serait si simple \n" 
;
00543     echo "d'exécuter si on avait assez de mémoire&nbsp;: \n" 
;
00544     finp
() ;
00545     
00546     #% le "vrai" fichier est trilignes.r dans le répertoire Metaseed/Genomes.
00547     # % 63 401 430 lues dans genomes.fasta
00548     
00549     pre_fichier
("sortlines.r","cadre") ;
00550     
00551     p
("texte") ;
00552     echo "Dans ce cas, \n" 
;
00553     echo "pour notre fichier de test, dont la taille est d'environ 3,9 giga-octets, la lecture \n" 
;
00554     echo "des 63,4 millions de lignes prend environ 5 minutes et le tri 20 minutes -- l'ordinateur \n" 
;
00555     echo "utilisé ici \n" 
;
00556     echo "est relativement assez puissant et, surtout, il a 32 giga-octets de mémoire. Il est clair \n" 
;
00557     echo "qu'avec une machine plus limitée en mémoire, cela va prendre encore plus de temps. \n" 
;
00558     finp
() ;
00559     
00560     p
("texte") ;
00561     echo "Nous avons essayé d'exécuter le même code sur une machine "
.em("Windows")." avec effectivement \n" ;
00562     echo "2 giga-octets de mémoire. En mode session traditionnelle, 
$R ne se \"plaint\" pas \n" ;
00563     echo "mais n'affiche rien. Le prompt réapparait au bout de quelques minutes mais plus rien ne fonctionne&nbsp;: \n" 
;
00564     echo "à chaque nouvelle instruction exécutée, 
$R répond de façon ".em("sybilline")."&nbsp;: \n" ;
00565     finp
() ;
00566     
00567     pre_fichier
("sortlines01.txt","cadre") ;
00568     
00569     p
("texte") ;
00570     echo "Avec 
$rstudio, ce n'est guère mieux. Au bout de quelques minutes aussi apparait le message \n" ;
00571     echo "cette fois un peu plus explicite&nbsp;: \n" 
;
00572     finp
() ;
00573     
00574     pre_fichier
("sortlines02.txt","cadre") ;
00575     
00576     p
("texte") ;
00577     echo "Pour mettre au point le script qui effectue la lecture et le tri, "
.b("il ne faut surtout pas")." \n" ;
00578     echo b
("utiliser le gros fichier")." car mettre 30 minutes ou plus à chaque essai se révèlera catastrophique \n" ;
00579     echo "en temps. Comme souvent dans ce genre de programmation, il faut écrire et affiner le script sur \n" 
;
00580     echo "un petit jeu d'essai avant de tester sans doute une et une seule fois l'exécution sur le gros fichier. \n" 
;
00581     finp
() ;
00582     
00583     p
("texte") ;
00584     echo "Puisqu'on ne peut pas charger le fichier des données en mémoire, il faut le \n" 
;
00585     echo "scinder en plusieurs petits fichiers puis faire un tri-fusion de ces petits fichiers. \n" 
;
00586     echo "Par exemple, 3,9&nbsp;Go divisés par trois donne 1,3&nbsp;Go qui est inférieur à la taille de \n" 
;
00587     echo "la mémoire de la machine. \n" 
;
00588     finp
() ;
00589     
00590     p
("texte") ;
00591     echo "Un tri-fusion consiste à trier chacun de deux fichiers obtenus, disons A et B \n" 
;
00592     echo "puis à fusionner les fichiers triés. \n" 
;
00593     echo "Pour cela, on lit au fur et à mesure dans chacun des deux fichiers triés, une ligne à \n" 
;
00594     echo "la fois, ce qui ne prend presque rien en mémoire, pour écrire dans le fichier \n" 
;
00595     echo "résultat C. Voici un exemple élémentaire d'exécution avec 3 lignes dans A \n" 
;
00596     echo "et deux lignes dans B. \n" 
;
00597     finp
() ;
00598     
00599     p
("texte") ;
00600     echo "Suppons que le contenu des fichiers soit&nbsp;: \n" 
;
00601     finp
() ;
00602     
00603     pre_fichier
("trifusAB.txt","cadre") ;
00604     
00605     p
("texte") ;
00606     echo "Alors l'exécution du tri-fusion des fichiers A et B se fait en 5 étapes&nbsp;:" 
;
00607     finp
() ;
00608     
00609     pre_fichier
("trifus1.txt","cadre") ;
00610     
00611     p
("texte") ;
00612     echo "Après réflexion, nous n'avons sans doute pas besoin d'effectuer un tri-fusion de l'ensemble des fichiers \n" 
;
00613     echo "puisqu'on s'intéresse seulement aux cinq premières lignes. On doit pouvoir se contenter de trier chaque partie \n" 
;
00614     echo "de fichier lu et de ne conserver que les  cinq premières lignes de chaque partie pour tout trier ensuite. \n" 
;
00615     finp
() ;
00616     
00617     p
("texte") ;
00618     echo "Voici donc ce qu'on va utiliser comme méthode&nbsp;: \n" 
;
00619     finp
() ;
00620     
00621     ol
() ;
00622     
00623     debutli
() ; p() ;
00624     echo "déterminer le nombre "
.b("n")." de lignes du fichier&nbsp;; \n" ;
00625     finp
() ; finli() ;
00626     
00627     debutli
() ; p() ;
00628     echo "lire la première moitié du fichier, trier et garder les 5 premières lignes&nbsp;; \n" 
;
00629     finp
() ; finli() ;
00630     
00631     debutli
() ; p() ;
00632     echo "lire la seconde moitié du fichier, trier et garder les 5 premières lignes&nbsp;; \n" 
;
00633     finp
() ; finli() ;
00634     
00635     debutli
() ; p() ;
00636     echo "fusionner les deux séries de 5 lignes, trier et ne retenir que les les 5 premières lignes. \n" 
;
00637     finp
() ; finli() ;
00638     
00639     finol
() ;
00640     
00641     p
("texte") ;
00642     echo "Une première difficulté surgit avec la détermination du nombre de lignes en tout dans le gros fichier \n" 
;
00643     echo "et dans la lecture de chacune des parties&nbsp;: la fonction standard  "
.noir("readLines()")." n'est pas prévue pour cela. \n" ;
00644     finp
() ;
00645     
00646     p
("texte") ;
00647     echo "En effet, pour trouver le nombre de lignes du gros fichier initial, il n'est pas possible d'utiliser \n" 
;
00648     echo "la fonction de base  "
.noir("readLines()")." car elle met en mémoire toutes les lignes du fichier. \n" ;
00649     echo "Il faut utiliser la fonction  "
.noir("determine_nlines()")." du package ".hrrp("LaF")." dont le titre complet est \n" ;
00650     echo bleu
("Fast access to large ASCII files").". De même pour lire les lignes ".noir("n".sub("1"))." à ".noir("n".sub("2"))." d'un fichier, \n" ;
00651     echo "il faut passer par la fonction \n" 
;
00652     echo " "
.noir("n.readLines()")." du package ".hrrp("reader")." \n" ;
00653     echo "dont le titre complet est "
.bleu("Suite of Functions to Flexibly Read Data from Files").". \n" ;
00654     finp
() ;
00655     
00656     p
("texte") ;
00657     echo "Nous écrivons la fonction  "
.noir("prem5(fichier)")." suivante pour automatiser les étapes 2 et 3 \n" ;
00658     echo "qui sont identiques, aux numéros de lignes à lire près&nbsp;: \n" 
;
00659     finp
() ;
00660     
00661     pre_fichier
("prem5.r","cadre") ;
00662     
00663     p
("texte") ;
00664     echo "Dans la mesure où l'exécution prend beaucoup de temps, il est prudent de mettre un affichage dès qu'une étape \n" 
;
00665     echo "est réalisée. De plus, au niveau de chaque instruction, disons par exemple "
.noir("nbl &lt;- determine_nlines(fichier)").", \n" ;
00666     echo "dans une phase préliminaire, il est prudent d'afficher la durée d'exécution de l'instruction à l'aide la fonction \n" 
;
00667     echo " "
.noir("duree()")." des exercices de la séance 5, afin d'avoir une idée précise de la durée de chaque étape, soit le code&nbsp;: \n" ;
00668     finp
() ;
00669     
00670     pre_fichier
("insdure.r","cadre") ;
00671     
00672     p
("texte") ;
00673     echo "Une fois mis au moins et testé sur plusieurs fichiers, \n" 
;
00674     echo "le code qui implémente notre méthode est le suivant&nbsp;: \n" 
;
00675     finp
() ;
00676     
00677     pre_fichier
("trifus2.r","cadre") ;
00678     
00679     /*
00680     p("texte") ;
00681     echo "Les temps d'exécution sont... \n" ;
00682     finp() ;
00683     */
00684     
00685     #pre_fichier("trifus2.txt","cadre") ; ==> trouver le résultat et le rajouter
00686     
00687     p
("texte") ;
00688     echo "Pour en terminer avec cet exercice, on peut sans doute affirmer que le code "
.noir("sort(V,dec=TRUE)")." est vraiment plus \n" ;
00689     echo "rapide que le code "
.noir("rev(sort(V))").", avec un gain d'environ 10&nbsp;% comme on peut s'en rendre \n" ;
00690     echo "compte à l'aide nombreux exemples. Ainsi&nbsp;: \n" 
;
00691     finp
() ;
00692     
00693     pre_fichier
("sortrev.txt","cadre") ;
00694     
00695     $img 
"sortrev.png" ;
00696     p
() ;
00697     nbsp
(4) ;
00698     echo href
($img,img($img,"",600)) ;
00699     finp
() ;
00700     
00701     
00702     finsolution
() ;
00703     
00704     finblockquote
() ;
00705     
00706     ## -------------------------------------------------------------------------------------------
00707     
00708     finPageExercices
($numSerie) ; # contient finSection() et finPage() ; la fonction est dans progi.php
00709     ?>

Pour ne pas voir les numéros de ligne, ajoutez &nl=non à la suite du nom du fichier.

 

 

retour gH    Retour à la page principale de   (gH)