Listing du fichier td2.php
00001<?php
00002 # # (gH) -_- td2.php ; TimeStamp (unix) : 24 Juin 2018 vers 20:37
00003 error_reporting(E_ALL | E_NOTICE | E_STRICT ) ;
00004 header('Content-Type "text/html; charset=iso-8859-1"') ;
00005 ini_set( 'default_charset', 'ISO-8859-1' );
00006 include("decra-inc.php") ;
00007
00008 $numSerie = 2 ;
00009 debutTDi($numSerie,"Structuration, instructions vectorielles, boucles et optimisation") ;
00010 ghAtAngers() ;
00011
00012 $R = ghRouge("R") ;
00013 $XML = ghRouge("XML") ;
00014 $Awk = ghRouge("AWK") ;
00015 $Php = ghVert("PHP") ;
00016 $Python = ghVert("Python") ;
00017 $APL = ghBleu("APL") ;
00018
00019 ## -------------------------------------------------------------------------------------------
00020
00021 sdl(3) ; echo cmt(' pour afficher toutes les solutions : td2.php?solutions=1') ; sdl(3) ;
00022
00023 ## -------------------------------------------------------------------------------------------
00024
00025 p("texte") ;
00026 echo "" ;
00027 finp() ;
00028 debutSection() ;
00029
00030 $tableauDesRubriques = array() ;
00031 $idr = 0 ;
00032 $idr++; $tableauDesRubriques[$idr] = "Structuration dans le développement Web" ;
00033 $idr++; $tableauDesRubriques[$idr] = "Instructions vectorielles et fonctionnelles (1)" ;
00034 $idr++; $tableauDesRubriques[$idr] = "Instructions vectorielles et fonctionnelles (2)" ;
00035 $idr++; $tableauDesRubriques[$idr] = "Boucles et optimisation (1)" ;
00036 $idr++; $tableauDesRubriques[$idr] = "Boucles et optimisation (2)" ;
00037 $idr++; $tableauDesRubriques[$idr] = "Optimisation dans le développement Web" ;
00038 $tdmCRLM = new tdm($tableauDesRubriques) ;
00039 $tdmCRLM->titre() ;
00040 $tdmCRLM->menu("oui","oui","nou") ;
00041
00042 direAfficherSolutionsTD($numSerie) ;
00043
00044 finSection() ;
00045
00046 $numExo = 0 ;
00047
00048 ## -------------------------------------------------------------------------------------------
00049
00050 $tdmCRLM->afficheRubrique("oui") ; $numExo++ ; # Structuration dans le développement Web
00051
00052 ## -------------------------------------------------------------------------------------------
00053
00054 blockquote() ; # td
00055
00056 blockquote() ; # énoncé
00057
00058 p("texte") ;
00059 echo " Comment fait-on pour structurer une page Web ou un site Web en PHP ?" ;
00060 echo " Comment fait-on pour structurer un programme en général ?" ;
00061 finp() ;
00062
00063 p("texte") ;
00064 echo " Faut-il passer à des sites Web non écrits en PHP ?" ;
00065 echo " Que signifie le terme ".b("full stack")." ?" ;
00066 finp() ;
00067
00068 finblockquote() ; # énoncé
00069
00070 solutionTD($numExo,$numSerie) ;
00071
00072 p("texte") ;
00073 echo " Il n'y a pas de solution générale à la structuration, que ce soit " ;
00074 echo " une page Web, un site Web ou un programme en général, " ;
00075 echo " même si la plupart des langages de programmation fournissent des moyens d'inclure des " ;
00076 echo " fichiers. Rien n'indique en effet comment découper le code ou quelles fonctions mettre " ;
00077 echo " dans quels fichiers. " ;
00078 finp() ;
00079
00080 p("texte") ;
00081 echo " Structurer une page Web consiste en général à ".b("externaliser")." le code CSS et le code Javascript, " ;
00082 echo " et sans à doute définir des sous-programmes d'affichage. En fonction de l'importance de la page, " ;
00083 echo " on viendra donc inclure ou plusieurs fichiers PHP, on utilisera des bibliothèques Javascript " ;
00084 echo " pour le ".href("https://en.wikipedia.org/wiki/Front_and_back_ends","front end") ;
00085 $url = "https://www.alticreation.com/difference-developpeur-front-end-et-developpeur-back-end/" ;
00086 echo " et le ".href($url,"back end")."." ;
00087 finp() ;
00088
00089 p("texte") ;
00090 echo " Comment structurer un site page Web est un problème compliqué. " ;
00091 echo " La tendance actuelle (2018) consiste plutôt, pour un blog ou un site de moyenne importance, " ;
00092 echo " à passer par un générateur de sites " ;
00093 echo " nommé dans ce contexte " ;
00094 echo href("https://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_contenu","CMS") ;
00095 echo " comme par exemple " ;
00096 echo href("https://fr.wikipedia.org/wiki/WordPress","WordPress").". " ;
00097 echo " Pour des sites plus complets, ou si on préfère plus de controle sur le site, il est conseillé " ;
00098 echo " de passer par un framework de développement comme " ;
00099 echo href("https://fr.wikipedia.org/wiki/Laravel","Laravel").", ";
00100 echo href("https://fr.wikipedia.org/wiki/CakePHP","CakePHP").", ";
00101 echo href("https://fr.wikipedia.org/wiki/Symfony","Symfony").", ";
00102 echo href("https://fr.wikipedia.org/wiki/CodeIgniter","CodeIgniter")." ou ";
00103 echo href("https://fr.wikipedia.org/wiki/Joomla!","Joomla").". ";
00104 echo " La plupart des sites ainsi générés sont alors structurés selon une architecture proche de " ;
00105 echo href("https://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur","MVC") ;
00106 echo " plutôt que d'une architecture " ;
00107 echo href("https://fr.wikipedia.org/wiki/Architecture_trois_tiers","trois tiers")."." ;
00108 finp() ;
00109
00110 p("texte") ;
00111 echo " La question de savoir s'il faut développer en PHP, en Java ou autre langage n'est pas un problème simple. " ;
00112 echo " La popularité de " ;
00113 echo href("https://fr.wikipedia.org/wiki/Django_(framework)","Django").", " ;
00114 echo href("https://fr.wikipedia.org/wiki/Ruby_on_Rails","Ruby on Rails")." et " ;
00115 echo href("https://fr.wikipedia.org/wiki/Node.js","NodeJs") ;
00116 echo " montre que PHP et Java ne sont pas les seuls langages possibles pour développer des sites Web. " ;
00117 echo " Les langages utilisés, respectivement Python, Ruby et Javascript, " ;
00118 echo " ont suffisamment d'avantages pour qu'on se pose la question de leur utilisation." ;
00119 finp() ;
00120
00121 p("texte") ;
00122 echo " Le terme ".b("fullstack")." fait référence à des compétences de développement Web " ;
00123 echo " qui couvrent tous les aspects du développement. On pourra consulter la page Web de " ;
00124 echo href(" https://fr.wikipedia.org/wiki/D%C3%A9veloppeur_full_stack","wikipedia") ;
00125 echo " sur le sujet." ;
00126 finp() ;
00127
00128 p() ;
00129 nbsp(5) ;
00130 $img = "backendfrontend.jpg" ;
00131 echo href($img,img($img,"",500)) ;
00132 finp() ;
00133
00134 finsolution() ; # contient un blockquote
00135
00136 finblockquote() ; # td
00137
00138 ## -------------------------------------------------------------------------------------------
00139
00140 $tdmCRLM->afficheRubrique("oui") ; $numExo++ ; # Instructions vectorielles (1)
00141
00142 ## -------------------------------------------------------------------------------------------
00143
00144 blockquote() ; # td
00145
00146 blockquote() ; # énoncé
00147
00148 p("texte doubleInterligne") ;
00149 echo " La programmation vectorielle met en jeu des instructions basées, soit en entrée, soit en sortie, sur des structures de type tableau mais nommées " ;
00150 echo ' vecteurs par analogie avec les vecteurs mathématiques de '.ghBleu('$\mathbf{\Bbb{R}^n}$').'. ' ;
00151 echo ' On notera pour cet exercice $V_i$ la i-ème composante du vecteur $V$, équivalente à V[i] ou V[i-1] pour l\'informatique. ' ;
00152 echo " Les calculs usuels s'étendent naturellement aux vecteurs, comme en mathématiques, dès lors que les contraintes de longueur sont respectées. " ;
00153 echo ' En particulier, pour un vecteur $V$ et un nombre $a$, le vecteur $aV$ a pour i-ème composante la valeur $aV_i$. ' ;
00154 echo ' Pour deux vecteurs $V$ et $W$ de même longueur, $V+W$ est le vecteur dont la i-ème composante est $V_i+W_i$, ' ;
00155 echo ' et $V\times{}W$ est le vecteur dont la i-ème composante est $V_i\times{}W_i$ («produit scalaire»). ' ;
00156 finp() ;
00157
00158 p("texte") ;
00159 echo " On admettra pour ce qui suit qu'on dispose des fonctions vectorielles suivantes :" ;
00160 finp() ;
00161
00162 ul() ;
00163
00164 debutli() ; p() ;
00165 echo b("indices(n)").' qui renvoie, pour un entier $n$, le vecteur de longueur $n$ dont la i-ème composante est $i$ ' ;
00166 finp() ; finli() ;
00167
00168 debutli() ; p() ;
00169 echo b("longueur(V)")." qui renvoie le nombre d'éléments du vecteur V ;" ;
00170 finp() ; finli() ;
00171
00172 debutli() ; p() ;
00173 echo b("somme(V)")." qui renvoie la somme des éléments du vecteur V ;" ;
00174 finp() ; finli() ;
00175
00176 debutli() ; p() ;
00177 echo b("produit(V)")." qui renvoie le produit des éléments du vecteur V ;" ;
00178 finp() ; finli() ;
00179
00180 debutli() ; p() ;
00181 echo b("cumul(V)")." qui renvoie le vecteur des sommes cumulées de V ;" ;
00182 finp() ; finli() ;
00183
00184 finul() ;
00185
00186 p("texte") ;
00187 echo "Donner les instructions vectorielles qui permettent de calculer :" ;
00188 finp() ;
00189
00190 ul("class='tirets'") ;
00191
00192 debutli() ; p() ;
00193 echo '- le vecteur $I$ des $n$ premiers entiers ;' ;
00194 finp() ; finli() ;
00195
00196 debutli() ; p() ;
00197 echo '- la somme $S = \sum i$ des $n$ premiers entiers ;' ;
00198 finp() ; finli() ;
00199
00200 debutli() ; p() ;
00201 echo '- la somme $C = \sum i^2$ des n premiers carrés d\'entiers ;' ;
00202 finp() ; finli() ;
00203
00204 debutli() ; p() ;
00205 echo '- la valeur $F = n!$ ("factorielle n") ;' ;
00206 finp() ; finli() ;
00207
00208 debutli() ; p() ;
00209 echo '- la moyenne $M$ et la variance (empirique) $V$ d\'un vecteur $W$ numérique ;' ;
00210 finp() ; finli() ;
00211
00212 debutli() ; p() ;
00213 echo '- le vecteur $P$ des fréquences cumulées d\'un vecteur $W$ d\'effectifs (positifs ou nuls) de somme non nulle.' ;
00214 finp() ; finli() ;
00215
00216 finul() ;
00217
00218 p("texte") ;
00219 echo ' On pourra imaginer que $n$ vaut 5 pour vérifier les calculs à la main, et que $W$ est le vecteur (1,5,3,1). ' ;
00220 finp() ;
00221
00222 p("texte") ;
00223 echo "Quels langages implémentent de tels calculs ?" ;
00224 echo " Quelle est alors la syntaxe exacte à utiliser ?" ;
00225 finp() ;
00226
00227 finblockquote() ; # énoncé
00228
00229 solutionTD($numExo,$numSerie) ; # contient un blockquote
00230
00231 p("texte") ;
00232 echo "Les langages $R et $APL implémentent ces calculs de façon native. $Python les implémente via le package " ;
00233 echo href("https://numpy.org/",b("NumPy")).". " ;
00234 echo " Sans rien installer, pour $APL, on peut utiliser le site " ;
00235 echo href("https://tryapl.org","tryapl.org")." à cause des caractères spéciaux. " ;
00236 echo " Pour $R et $Python, là encore sans rien installer, on peut utiliser en ligne, le site " ;
00237 echo href("https://repl.it")." ou les ".b("jupyter notebook")." à l'adresse " ;
00238 echo href("http://jupyter.org/try","try jupyter").". " ;
00239 finp() ;
00240
00241 p("texte") ;
00242 echo " Pour $Python, on a \"importé\" les fonctions array, arange et shape de numpy. " ;
00243 echo " Certaines solutions avec la syntaxe objet ont un équivalent traditionnel, comme par exemple " ;
00244 echo b("sum(I)")." au lieu de ".b("I.sum()")."." ;
00245 finp() ;
00246
00247 # vérification avec td2vect1.r et td2vect1.py et td2vect1bis.py
00248
00249 blockquote() ; # tableau
00250 table(1,15,"collapse") ;
00251 entetesTableau("Algorithmique Langage__R Langage__APL Langage__Python Résultat") ;
00252
00253 tr() ;
00254 td() ; echo tt(" I <-- indices(n)") ; fintd() ;
00255 td() ; echo tt(" I <- 1:n") ; fintd() ;
00256 td() ; echo tt(" I ← ιn") ; fintd() ;
00257 td() ; echo tt(" I = arange(1,n+1)") ; fintd() ;
00258 td() ; echo tt("(1,2,3,4,5)") ; fintd() ;
00259 fintr() ;
00260
00261 tr() ;
00262 td() ; echo tt(" S <-- somme(I)") ; fintd() ;
00263 td() ; echo tt(" S <- sum(I)") ; fintd() ;
00264 td() ; echo tt(" S ← +/I") ; fintd() ;
00265 td() ; echo tt(" S = I.sum()") ; fintd() ;
00266 td("R") ; echo tt("15") ; fintd() ;
00267 fintr() ;
00268
00269 tr() ;
00270 td() ; echo tt(" C <-- somme(I×I)") ; fintd() ;
00271 td() ; echo tt(" C <- sum(I*I)") ; fintd() ;
00272 td() ; echo tt(" C ← +/I×I") ; fintd() ;
00273 td() ; echo tt(" C = (I*I).sum()") ; fintd() ;
00274 td("R") ; echo tt("55") ; fintd() ;
00275 fintr() ;
00276
00277 tr() ;
00278 td() ; echo tt(" F <-- produit(I)") ; fintd() ;
00279 td() ; echo tt(" F <- prod(I)") ; fintd() ;
00280 td() ; echo tt(" F ← ×/I") ; fintd() ;
00281 td() ; echo tt(" F = I.prod()") ; fintd() ;
00282 td("R") ; echo tt("120") ; fintd() ;
00283 fintr() ;
00284
00285 tr() ;
00286 td() ; echo tt(" M <-- somme(W) / longueur(W)") ; fintd() ;
00287 td() ; echo tt(" M <- sum(W) / length(W)") ; fintd() ;
00288 td() ; echo tt(" M ← (+/W) ÷ ρW") ; fintd() ;
00289 td() ; echo tt(" M = W.sum()/shape(W)") ; fintd() ;
00290 td("R") ; echo tt("2.5") ; fintd() ;
00291 fintr() ;
00292
00293 tr() ;
00294 td() ; echo tt(" V <-- somme( (W-M)^2 ) / longueur(W)") ; fintd() ;
00295 td() ; echo tt(" V <- sum((W-M)**2) / length(W)") ; fintd() ;
00296 td() ; echo tt(" V ← (+/(W-M)*2)) ÷ ρW") ; fintd() ;
00297 td() ; echo tt(" sum((W-M)**2)/shape(W)") ; fintd() ;
00298 td("R") ; echo tt("2.75") ; fintd() ;
00299 fintr() ;
00300
00301 tr() ;
00302 td() ; echo tt(" P <-- cumul(W) / somme(W)") ; fintd() ;
00303 td() ; echo tt(" P <- cumsum(W) / sum(W)") ; fintd() ;
00304 td() ; echo tt(" P ← (+\\W) ÷ +/W") ; fintd() ;
00305 td() ; echo tt(" P = W.cumsum()/W.sum()") ; fintd() ;
00306 td() ; echo tt("(0.1,0.6,0.9,1.0)") ; fintd() ;
00307 fintr() ;
00308
00309 fintable() ;
00310 finblockquote() ; # tableau
00311
00312 # https://eric.univ-lyon2.fr/~ricco/cours/slides/PG%20-%20vecteurs%20avec%20numpy.pdf
00313 # import numpy as np OUI
00314 # np.sum(W) OUI mais W.sum() mieux W.shape pas W.shape() W.flags et W.size plutot que shape
00315 # from numpy import * surtout pas
00316 # W = np.array([1,5,3,1]) et W.cumsum()/W.sum()
00317 # http://math.mad.free.fr/depot/numpy/base.html
00318 # http://www.python-simple.com/python-numpy-scipy/statistics-numpy.php
00319
00320 p("texte") ;
00321 echo b("Remarques :") ;
00322 echo " $APL a une fonction spécialisée pour calculer factorielle n. Et l'opération de réduction via ".b("/") ;
00323 echo " peut s'appliquer à n'importe quel opérateur. " ;
00324 echo " $R a des fonctions spécialisées pour calculer factorielle n, la moyenne et la variance, " ;
00325 echo " sachant qu'en statistiques, il y a plusieurs variances " ;
00326 echo " (dont celle de l'échantillon, celle de la population sous-jacente)." ;
00327 echo " $Python, via NumPy notamment, dispose aussi de fonctions spécialisées pour réaliser de tels calculs." ;
00328 finp() ;
00329
00330 p("texte") ;
00331 echo ghRouge("Attention")." à l'écriture \"propre\" des appels de fonctions dans ces langages. " ;
00332 echo " Ainsi en $R, ".b("sum(I)*I")." et ".b("sum(I*I)")." sont tous deux des calculs valides mais qui ne fournissent pas le même résultat. " ;
00333 echo " En $Python aussi, avec ".b("I*I.sum()")." et ".b("(I*I).sum()").". " ;
00334 echo " Il est donc important de vérifier que le code produit bien ce qu'on veut." ;
00335 finp() ;
00336
00337 finsolution() ; # contient un blockquote
00338
00339 finblockquote() ; # td
00340
00341 ## -------------------------------------------------------------------------------------------
00342
00343 $tdmCRLM->afficheRubrique("oui") ; $numExo++ ; # Instructions vectorielles (2)
00344
00345 ## -------------------------------------------------------------------------------------------
00346
00347 blockquote() ; # td
00348
00349 blockquote() ; # énoncé
00350
00351 p("texte doubleInterligne") ;
00352 echo " On suppose désormais que les comparaisons logiques usuelles sont aussi des opérations vectorielles qui renvoient, indice par indice, " ;
00353 echo ' 0 lorsque le résultat du test est faux et 1 lorsque le résultat du test est vrai. ' ;
00354 echo ' Ainsi, pour le vecteur $V=(5,8,2,1,9)$, la comparaison $V>3$ renvoie $(1,1,0,0,1)$.' ;
00355 finp() ;
00356
00357 p("texte") ;
00358 echo ' Détailler ce que réalisent les calculs suivants écrits en '.$APL.', sachant que Γ correspond à la fonction '.b("max()").'. ' ;
00359 echo ' On pourra essayer d\'inventer la syntaxe algorithmique correspondante et on se posera la question de savoir comment ' ;
00360 echo ' écrire cela en '.$R.' puis en '.$Python.', sans doute là encore à l\'aide de NumPy.' ;
00361 finp() ;
00362
00363
00364 p("texte") ;
00365 echo b("Atttention")." : " ;
00366 echo $APL .' interprète les opérations à partir de la droite afin de minimiser le nombre de parenthèses à écrire. ' ;
00367 echo ' Ainsi 2 × 3 +5 correspond à 2 × (3 +5) soit 16.' ;
00368 finp() ;
00369
00370 blockquote() ; # tableau
00371 table(1,15,"collapse") ;
00372 entetesTableau("Numéro Instruction__APL Remarque") ;
00373
00374 tr() ;
00375 td("R") ; echo tt(1)." " ; fintd() ;
00376 td() ; echo " ".tt("V=W") ; fintd() ;
00377 td() ; echo "V et W sont des vecteurs numériques ou caractères" ; fintd() ;
00378 fintr() ;
00379
00380 tr() ;
00381 td("R") ; echo tt(2)." " ; fintd() ;
00382 td() ; echo " ".tt("+/V=W") ; fintd() ;
00383 td() ; echo "V et W sont des vecteurs numériques ou caractères" ; fintd() ;
00384 fintr() ;
00385
00386 tr() ;
00387 td("R") ; echo tt(3)." " ; fintd() ;
00388 td() ; echo " ".tt("+/V>0") ; fintd() ;
00389 td() ; echo "V est un vecteur numérique" ; fintd() ;
00390 fintr() ;
00391
00392 tr() ;
00393 td("R") ; echo tt(4)." " ; fintd() ;
00394 td() ; echo " ".tt("+/Γ/V=V") ; fintd() ;
00395 td() ; echo "V est un vecteur numérique" ; fintd() ;
00396 fintr() ;
00397
00398 tr() ;
00399 td("R") ; echo tt(5)." " ; fintd() ;
00400 td() ; echo " ".tt("+/V=Γ/V") ; fintd() ;
00401 td() ; echo "V est un vecteur numérique" ; fintd() ;
00402 fintr() ;
00403
00404 tr() ;
00405 td("R") ; echo tt(6)." " ; fintd() ;
00406 td() ; echo " ".tt('+/V$\times$W') ; fintd() ;
00407 td() ; echo "V est un vecteur numérique" ; fintd() ;
00408 fintr() ;
00409
00410 tr() ;
00411 td("R") ; echo tt(7)." " ; fintd() ;
00412 td() ; echo " ".tt('+/V$\times$V') ; fintd() ;
00413 td() ; echo "V est un vecteur numérique" ; fintd() ;
00414 fintr() ;
00415
00416 fintable() ;
00417 finblockquote() ; # tableau
00418
00419 p("texte") ;
00420 echo " On commencera par donner le vecteur résultat correspondand à chaque instruction " ;
00421 echo ' pour les vecteurs $V=(5,8,-2,1,8)$ ' ;
00422 echo ' et $W=(5,8,2,1,9)$. ' ;
00423 finp() ;
00424
00425 finblockquote() ; # énoncé
00426
00427 solutionTD($numExo,$numSerie) ; # contient un blockquote
00428
00429 p("texte") ;
00430 echo 'Voici les résultats pour les vecteurs $V$ et $W$ fournis :' ;
00431 finp() ;
00432
00433 blockquote() ; # tableau
00434 table(1,15,"collapse") ;
00435 entetesTableau("Numéro Instruction__APL Résultat Remarque(s)") ;
00436
00437 tr() ;
00438 td("R") ; echo tt(1)." " ; fintd() ;
00439 td() ; echo tt("V=W") ; fintd() ;
00440 td() ; echo '($1,1,0,1,0)$' ; fintd() ;
00441 td() ; echo " Les différences sont aux indices 3 et 5." ; fintd() ;
00442 fintr() ;
00443
00444 tr() ;
00445 td("R") ; echo tt(2)." " ; fintd() ;
00446 td() ; echo tt("+/V=W") ; fintd() ;
00447 td() ; echo "3" ; fintd() ;
00448 td() ; echo "C'est la somme du vecteur précédent." ; fintd() ;
00449 fintr() ;
00450
00451 tr() ;
00452 td("R") ; echo tt(3)." " ; fintd() ;
00453 td() ; echo tt("+/V>0") ; fintd() ;
00454 td() ; echo "4" ; fintd() ;
00455 td() ; echo 'Il y a 4 valeurs strictement positives dans $V$.' ; fintd() ;
00456 fintr() ;
00457
00458 tr() ;
00459 td("R") ; echo tt(4)." " ; fintd() ;
00460 td() ; echo tt("+/Γ/V=V") ; fintd() ;
00461 td() ; echo "1" ; fintd() ;
00462 td() ; echo '$V=V$ renvoie $(1,1,1,1,1)$. ($Γ/V=V$) est donc 1 et $+/1$ renvoie 1.' ; fintd() ;
00463 fintr() ;
00464
00465 tr() ;
00466 td("R") ; echo tt(5)." " ; fintd() ;
00467 td() ; echo tt("+/V=Γ/V") ; fintd() ;
00468 td() ; echo "2" ; fintd() ;
00469 td() ; echo 'Γ/V est 8. $V=Γ/V$ est $(0,1,0,0,1)$. Sa somme est 2.' ; fintd() ;
00470 fintr() ;
00471
00472 tr() ;
00473 td("R") ; echo tt(6)." " ; fintd() ;
00474 td() ; echo " ".tt('+/V$\times$W') ; fintd() ;
00475 td() ; echo "158" ; fintd() ;
00476 td() ; echo 'V$\times$W est (25,64,-4,1,72). Sa somme est 158.' ; fintd() ;
00477 fintr() ;
00478
00479 tr() ;
00480 td("R") ; echo tt(7)." " ; fintd() ;
00481 td() ; echo " ".tt('+/V$\times$V') ; fintd() ;
00482 td() ; echo "158 (aussi !)" ; fintd() ;
00483 td() ; echo 'V$\times$V est (25,64,4,1,64). Sa somme est 158.' ; fintd() ;
00484 fintr() ;
00485
00486 fintable() ;
00487 finblockquote() ; # tableau
00488 p("texte") ;
00489 echo "La première instruction renvoie le vecteur des comparaisons terme à terme des vecteurs V et W. " ;
00490 finp() ;
00491
00492 p("texte") ;
00493 echo " La deuxième instruction renvoie le nombre ".b("egal(V,W)")." de valeurs égales dans V et W à la même position. " ;
00494 echo " Un calcul lié à cette instruction est le nombre ".b("diff(V,W)")." de valeurs différentes entre V et W. " ;
00495 finp() ;
00496
00497 p("texte") ;
00498 echo " La fonction ".b('(V,W) $\mapsto$ diff(V,W)')." est nommée " ;
00499 echo href("https://fr.wikipedia.org/wiki/Distance_de_Hamming","distance de Hamming").". " ;
00500 echo " Cette distance est très utilisée en bioinformatique et en informatique textuelle." ;
00501 finp() ;
00502
00503 p("texte") ;
00504 echo " La troisième instruction renvoie le nombre de valeurs strictement positives dans le vecteur V. " ;
00505 finp() ;
00506
00507 p("texte") ;
00508 echo " La quatrième instruction correspond sans doute à une erreur de frappe. " ;
00509 echo " Elle renvoie 1 systématiquement." ;
00510 finp() ;
00511
00512 p("texte") ;
00513 echo " La cinquième instruction renvoie le nombre de valeurs dans le vecteur V " ;
00514 echo " égales au maximum de V. C'est sans doute la bonne version de l'instruction 4." ;
00515 finp() ;
00516
00517 p("texte") ;
00518 echo " La sixième instruction renvoie la somme des produits terme à terme des vecteurs V et W." ;
00519 echo " C'est donc ce qu'en algèbre (linéaire) on nomme le ".b("produit scalaire")." de ces vecteurs." ;
00520 finp() ;
00521
00522 p("texte") ;
00523 echo " La septième instruction renvoie le produit scalaire d'un vecteur avec lui-même." ;
00524 echo " C'est donc ce qu'en algèbre on nomme le ".b("carré de la norme")." de ce vecteur." ;
00525 finp() ;
00526
00527 p("texte") ;
00528 echo b("Code $R correspondant :") ;
00529 finp() ;
00530
00531 pre_fichier("td2vect2.r","cadrejaune") ;
00532
00533 p("texte") ;
00534 echo b("Résultats :") ;
00535 finp() ;
00536
00537 pre_fichier("td2vect2r.txt","cadre") ;
00538
00539 p("texte") ;
00540 echo b("Code $Python correspondant :") ;
00541 finp() ;
00542
00543 pre_fichier("td2vect2.py","cadrejaune") ;
00544
00545 p("texte") ;
00546 echo b("Résultats :") ;
00547 finp() ;
00548
00549 pre_fichier("td2vect2py.txt","cadre") ;
00550
00551 finsolution() ; # contient un blockquote
00552
00553 finblockquote() ; # td
00554
00555 ## -------------------------------------------------------------------------------------------
00556
00557 $tdmCRLM->afficheRubrique("oui") ; $numExo++ ; # Boucles et optimisation (1)
00558
00559 ## -------------------------------------------------------------------------------------------
00560
00561 blockquote() ; # td
00562
00563 blockquote() ; # énoncé
00564
00565 p("texte") ;
00566 echo ' On se donne deux valeurs numériques $a$ et $b$ et un entier $n$. Ecrire un algorithme qui calcule les valeurs ' ;
00567 echo ' des $n$ points équidistants $x_i$, $i$ de 1 à $n$ avec $a=x_1$ et $b=x_n$. ' ;
00568 echo ' On commencera par trouver la formule qui sépare deux points sucessifs. ' ;
00569 echo ' On discutera s\'il faut utiliser une boucle '.b("pour").', ' ;
00570 echo ' une boucle '.b("tant que").', ou se passer de boucle et on viendra optimiser le nombre d\'opérations. ' ;
00571 finp() ;
00572
00573 p("texte") ;
00574 echo ' Au passage, que sont les $x_i$ pour $n=10$ avec $a=1$ et $b=10$ ?' ;
00575 echo ' Et pour $n=11$ avec $a=0$ et $b=1$ ?' ;
00576 finp() ;
00577
00578 p("texte") ;
00579 echo ' Trouver ensuite une solution vectorielle. ' ;
00580 #echo ' Quelles solutions sont proposées par '.$R.', '.$APL.' et '.$Python.' ?' ;
00581 echo ' Quelles solutions sont proposées par '.$R.' et '.$Python.' ?' ;
00582 finp() ;
00583
00584 finblockquote() ; # énoncé
00585
00586 solutionTD($numExo,$numSerie) ; # contient un blockquote
00587
00588 p("texte") ;
00589 echo " La formule mathématique pour calculer les ".'$x_i$'." est bien sûr :";
00590 finp() ;
00591
00592 p("texte plusgros") ;
00593 nbsp(7) ;
00594 echo '$x_i = a + (i-1)\times \displaystyle\frac{(b-a)}{(n-1)}$' ;
00595 finp() ;
00596
00597 p("texte") ;
00598 echo ' Pour $n=10$, avec $a=1$ et $b=10$, les $x_i$ sont les nombres de 1 à 10.' ;
00599 finp() ;
00600
00601 p("texte") ;
00602 echo ' Pour $n=11$, avec $a=0$ et $b=1$, les valeurs sont 0 0.1 0.2... 1.0.' ;
00603 finp() ;
00604
00605 p("texte") ;
00606 echo " La programmation naïve de la formule ne pose aucun problème :" ;
00607 finp() ;
00608
00609 pre_fichier("xi01.alg","cadrebleu") ;
00610
00611 p("texte") ;
00612 echo " Une première optimisation de la boucle consiste à sortir les «constantes» de la boucle " ;
00613 echo " et à initialiser le vecteur de sortie, soit le code :" ;
00614 finp() ;
00615
00616 pre_fichier("xi02.alg","cadrebleu") ;
00617
00618 p("texte") ;
00619 echo ' Une deuxième optimisation consiste à remarquer que les $x_i$ sont en progression arithmétique, ' ;
00620 echo ' donc il suffit de rajouter le pas $h$ de la progression pour passer d\'un point à l\'autre :' ;
00621 finp() ;
00622
00623 pre_fichier("xi03.alg","cadrebleu") ;
00624
00625 p("texte") ;
00626 echo " Bien sûr le calcul vectoriel permet de se passer de boucle :" ;
00627 finp() ;
00628
00629 pre_fichier("xi04.alg","cadrebleu") ;
00630
00631 p("texte") ;
00632 echo " Voici à titre d'exemple les versions 1 et 4 en $R :" ;
00633 finp() ;
00634
00635 pre_fichier("xi01et4.r","cadrejaune") ;
00636
00637 p("texte") ;
00638 echo " Et leur équivalent en $Python :" ;
00639 finp() ;
00640
00641 pre_fichier("xi01et4.py","cadrejaune") ;
00642
00643 p("texte") ;
00644 echo "La \"vraie\" solution se nomme ".b("seq()")." en $R et ".b("linspace()")." en $Python".ghvert(" / NumPy")." avec les syntaxes suivantes :" ;
00645 finp() ;
00646
00647 pre_fichier("xi01et4.sol","cadrebleu") ;
00648
00649 finsolution() ; # contient un blockquote
00650
00651 finblockquote() ; # td
00652
00653 ## -------------------------------------------------------------------------------------------
00654
00655 $tdmCRLM->afficheRubrique("oui") ; $numExo++ ; # Boucles et optimisation (2)
00656
00657 ## -------------------------------------------------------------------------------------------
00658
00659 blockquote() ; # td
00660
00661 blockquote() ; # énoncé
00662
00663 p("texte") ;
00664 echo ' Comment calculer de façon optimisée le maximum, le nombre d\'occurrences de ce maximum et sa première position pour un vecteur $V$ ?' ;
00665 finp() ;
00666
00667 p("texte") ;
00668 echo ' Est-ce qu\'une solution vectorielle pour ce problème est forcément optimisée ? ' ;
00669 finp() ;
00670
00671 p("texte") ;
00672 echo 'Quelles solutions sont proposées par '.$R.', '.$APL.' et '.$Python.' ?' ;
00673 finp() ;
00674
00675 p("texte") ;
00676 echo "Le code proposé est-il valide pour des vecteurs de chaines de caractères plutôt que pour des vecteurs de nombres ?" ;
00677 finp() ;
00678
00679 finblockquote() ; # énoncé
00680
00681 solutionTD($numExo,$numSerie) ; # contient un blockquote
00682
00683 p("texte") ;
00684 echo " Un algorithme qui passe en revue chaque élément et décide si c'est le nouveau maximum (donc une seule occurrence) " ;
00685 echo " ou le maximum local (c'est-à-dire le maximum trouvé jusque-là, donc une occurrence de plus) est certainement un " ;
00686 echo " algorithme optimisé qui peut s'écrire en une seule boucle POUR, comme ci-dessous :" ;
00687 finp() ;
00688
00689 pre_fichier("maxocc1.alg","cadre") ;
00690
00691 p("texte") ;
00692 echo " Une solution vectorielle pour compter le nombre d'occurrences du maximum " ;
00693 echo " par exemple avec le code ".b("somme( V=max(V) )")." est certes courte à écrire mais effectue deux parcours du vecteur. " ;
00694 echo " Cela s'écrit " ;
00695 echo b(s_span(tt("+/V=Γ/V"),"plusgros"))." en $APL, " ;
00696 echo b(s_span(tt("sum( V==max(V) )"),"plusgros"))." en $R et " ;
00697 echo b(s_span(tt("(V==max(V)).sum()"),"plusgros"))." en $Python. " ;
00698 finp() ;
00699
00700 p("texte") ;
00701 echo " Une telle écriture est sans doute suffisante car le code sous-jacent est très rapide, même pour des millions d'éléments. " ;
00702 echo " Il faudrait vraiment avoir des milliers de chaines d'ADN humain complètes (3 milliards de caractères) à comparer pour que ce code vectoriel soit moins efficace que notre algorithme." ;
00703 finp() ;
00704
00705 p("texte") ;
00706 echo "Nous ne donnons pas ici, volontairement, les solutions vectorielles en $R, $APL et $Python pour trouver la première position du maximum. " ;
00707 echo " Symboliquement, ce pourrait être ".b("premier( V=max(V) )")." mais il faudrait alors \"sortir\" le vecteur ".b("V=max(V)") ;
00708 echo " de ce calcul pour éviter de le recalculer deux fois afin de résoudre le problème complet posé. " ;
00709 echo " Les solutions algorithmiques correspondantes sont indiquées ci-dessous." ;
00710 finp() ;
00711
00712 p() ;
00713 echo b("Version vectorielle non optimisée") ;
00714 finp() ;
00715
00716 pre_fichier("maxocc2.alg","cadre") ;
00717
00718 p() ;
00719 echo b("Version vectorielle optimisée") ;
00720 finp() ;
00721
00722 pre_fichier("maxocc3.alg","cadre") ;
00723
00724 finsolution() ; # contient un blockquote
00725
00726 finblockquote() ; # td
00727
00728 ## -------------------------------------------------------------------------------------------
00729
00730 $tdmCRLM->afficheRubrique("oui") ; $numExo++ ; # Optimisation dans le développement Web
00731
00732 ## -------------------------------------------------------------------------------------------
00733
00734
00735 blockquote() ; # td
00736
00737 blockquote() ; # énoncé
00738
00739 p("texte") ;
00740 echo " Ce qu'on a vu précédemment montre que dans de nombreux cas, des calculs simples comme le maximum, les valeurs " ;
00741 echo " d'une suite arithmétique sont déjà programmés. Peut-on penser que dans l'utilisation de bases de données, on trouve " ;
00742 echo " le même genre de solutions pré-programmées ?" ;
00743 echo " Et dans le cas du développement Web ?" ;
00744 finp() ;
00745
00746 p("texte") ;
00747 echo "Comment garantir par exemple qu'une requête ".ghBleu("MySQL")." est optimisée ?" ;
00748 finp() ;
00749
00750 p("texte") ;
00751 echo "Comment tester la vitesse d'exécution de code en $R et en $Python ?" ;
00752 finp() ;
00753
00754 finblockquote() ; # énoncé
00755
00756 solutionTD($numExo,$numSerie) ; # contient un blockquote
00757
00758 p("texte") ;
00759 echo " Oui, bien sûr, des solutions pré-programmées existent déjà pour les bases de donnnées. " ;
00760 echo " Par exemple en SQL, pour calculer le maximum ou la moyenne, il existe des " ;
00761 echo " fonctions nommées " ;
00762 echo href("https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html","fonctions d'agrégation.")." " ;
00763 echo " comme min, max, avg et ".b("les")." variances." ;
00764 finp() ;
00765
00766 p("texte") ;
00767 echo " Savoir si une requête est optimisée, par contre, est loin d'être évident. " ;
00768 echo " Par exemple, comment savoir si la requête ci-dessous est optimisée ?" ;
00769 finp() ;
00770
00771 pre_fichier("reqSql-long.txt","cadrebleu") ;
00772
00773 p("texte") ;
00774 echo " Ou comment décider si la requête 1 ci-dessous " ;
00775 finp() ;
00776
00777 pre_fichier("req1mini.txt","cadrejaune") ;
00778
00779 p("texte") ;
00780 echo " s'exécute plus rapidement que la requête 2 suivante " ;
00781 finp() ;
00782
00783 pre_fichier("req2mini.txt","cadrejaune") ;
00784
00785 p("texte") ;
00786 echo " Même si MySQL, par exemple, dispose d'un " ;
00787 echo href("https://dev.mysql.com/doc/refman/8.0/en/show-profile.html","mécanisme de profilage") ;
00788 echo " dont le modèle est reproduit dans le texte qui suit " ;
00789 finp() ;
00790
00791 pre_fichier("profilingSql.txt","cadre") ;
00792
00793 p("texte") ;
00794 echo " il n'en demeure pas moins qu'exécuter une seule fois la requête et son profilage " ;
00795 echo " n'est certainement pas suffisant, sauf dans de très rares cas (à cause de l'encombrement " ;
00796 echo " mémoire, de la mise en cache des données, etc.). " ;
00797 echo " Donc on peut essayer d'estimer si une requête est optimisée, mais sans pouvoir vraiment " ;
00798 echo " le prouver." ;
00799 finp() ;
00800
00801 pre_fichier("req1et2.txt","cadrebleu") ;
00802
00803 p("texte") ;
00804 echo " Pour tester du code, $R et $Python fournissent aussi des instructions, respectivement " ;
00805 echo " la fonction " ;
00806 echo href("https://cran.r-project.org/web/packages/microbenchmark/index.html","microbenchmark") ;
00807 echo " du package ".em("eponyme")." et la fonction ".em("magique")." " ;
00808 echo href("https://ipython.org/ipython-doc/dev/interactive/magics.html#magic-timeit","%timeit")."." ;
00809 #echo href("https://docs.python.org/3/library/timeit.html","timeit")."." ;
00810 finp() ;
00811
00812 p("texte") ;
00813 echo "En voici des exemples d'utilisation :" ;
00814 finp() ;
00815
00816 pre_fichier("microbench.txt","cadrebleu") ;
00817
00818 pre_fichier("timeit.txt","cadrejaune") ;
00819
00820
00821 p("texte") ;
00822 echo " Ce qu'on doit retenir de tout cela, c'est principalement deux choses :" ;
00823 finp() ;
00824
00825 blockquote() ;
00826 ul() ;
00827
00828 debutli() ; p("texte") ;
00829 echo " de nombreuses solutions à des problèmes classiques sont déjà pré-programmées, disponibles et " ;
00830 echo " il vaut mieux les utiliser plutôt que de vouloir réinventer la roue et l'eau chaude " ;
00831 echo " parce que ces solutions sont ".b("robustes")." ;" ;
00832 finp() ; finli() ;
00833
00834 debutli() ; p("texte") ;
00835 echo " exécuter une fois le code pour avoir une idée de sa vitesse et de sa durée d'exécution " ;
00836 echo " n'est pas suffisant (il peut y avoir de la mise en cache des données, d'autres processus en mémoire...) " ;
00837 echo " et il vaut mieux utiliser des outils pour évaluer la performance ;" ;
00838 finp() ; finli() ;
00839
00840 debutli() ; p("texte") ;
00841 echo " il faut penser à se se poser la question de l'optimisation dès que la taille des données " ;
00842 echo " est importante ou dès que le problème risque d'exploser combinatoirement. " ;
00843 finp() ; finli() ;
00844
00845 finul() ;
00846 finblockquote() ;
00847
00848
00849 p("texte") ;
00850 echo "Code et graphiques (cliquables) non expliqués :" ;
00851 finp() ;
00852
00853 pre_fichier("microbench.r","cadrebleu") ;
00854
00855 p() ;
00856 nbsp(5) ;
00857 $img = "boxplot-mb.png" ;
00858 echo href($img,img($img,"",600)) ;
00859 finp() ;
00860
00861 p() ;
00862 nbsp(5) ;
00863 $img = "autoplot-mb.png" ;
00864 echo href($img,img($img,"",600)) ;
00865 finp() ;
00866
00867 finsolution() ; # contient un blockquote
00868
00869 finblockquote() ; # td
00870
00871 #############################################################################
00872
00873 finTDi($numSerie) ;
00874 ?>
Pour ne pas voir les numéros de ligne, ajoutez &nl=non à la suite du nom du fichier.
Retour à la page principale de (gH)