Introduction rapide pour le lycée François THIRIOUX [email protected] Lycée René Perrin – Ugine – Savoie version du 24 octobre 2015 [email protected] Table des matières 1 Julia express 2 2 Installer et lancer Julia 3 3 Structures usuelles 4 4 Matrices 5 5 Nombres complexes 10 6 Arithmétique 12 1 [email protected] 1. Julia express Introduction La question n’est pas de savoir qui est Julia : ce serait trop facile. Julia est un jeune langage de programmation créé au MIT en 2009, dont la syntaxe ressemble à celle de notre cher Python. Il possède une banque déjà fournie de modules additionnels, même si elle est moins impressionnante que celle de Python. Il existe deux avantages essentiels : • beaucoup de commandes mathématiques sont présentes nativement ; • sa rapidité d’exécution est proche de celle du C++. Il faut noter que la compilation est transparente pour l’utilisateur puisqu’elle est réalisée à la volée (« JIT », « Just In Time », du projet LLVM). Un programme en Julia s’exécute avec autant de facilité qu’un script en Python. Pour avoir une petite idée de la syntaxe et de la rapidité, voici en action un programme très subtil (...) affichant la liste des diviseurs d’un entier donné : Julia 0.3 Python 3.4 function diviseurs(n) for k in 1 : n if n%k == 0 println(k) end end end @time diviseurs(944986841) from time import time def diviseurs(n) : for k in range(1,n+1) : if n%k == 0 : print(k) a = time() diviseurs(944986841) b = time() print("durée : ",b-a," secondes") Résultat Résultat elapsed time: 8.857808039 seconds durée : 77.8134343624115 secondes Julia, un langage éco-responsable ! Notons par ailleurs que Julia supporte les caractères Unicode, ce qui, en français, signifie qu’on peut inclure dans un programme des lettres grecques ou des symboles spéciaux faisant office de variables, de fonctions, etc. Références et liens Le but de cette introduction n’est ni de réinventer la roue ni de se contenter de traduire les ressources existantes en français. Voici donc quelques liens essentiels : • site officiel : http://julialang.org ; • documentation officielle : http://docs.julialang.org ; • https://zestedesavoir.com/articles/141/a-la-decouverte-de-julia ; • http://learnxinyminutes.com/docs/julia ; • https://en.wikibooks.org/wiki/Introducing_Julia . Pour tester Julia sans rien installer, il existe le notebook https://www.juliabox.org . 2 [email protected] 2. Installer et lancer Julia Windows Les installeurs sont disponibles à l’adresse julialang.org/downloads . Testé rapidement, le reste de cette introduction est approfondi sous Ubuntu 15.10 . GNU-Linux/Ubuntu Il faut installer les paquets julia et git, présents dans les dépôts Ubuntu. Le second sert ici à récupérer les modules additionnels (« packages »). Modules additionnels Ouvrir un terminal et exécuter julia. Le mode interactif (comme en Python) est activé. Pour ajouter un module, la commande est Pkg.add("NomDuModule") . Ce module est stocké dans le répertoire ∼/.julia . Lorsque des paquets supplémentaires sont nécessaires, Julia fait appel à apt et demande le mot de passe administrateur. Pour quitter le mode interactif, taper Ctrl-D. Interfaces Un éditeur de texte suffit à créer un fichier bidule.jl . On peut ensuite l’exécuter simplement depuis un terminal via julia bidule.jl . La coloration syntaxique est prise en charge par un éditeur comme Gedit, mais pas l’indentation automatique. On pourra avantageusement créer un outil externe (greffon à activer dans les préférences de Gedit) avec la commande julia . On peut également utiliser Qt Creator, par exemple. Il faut configurer un Outil externe (comme pour Python) via les menus Outils/Options/Environnement/Outils externes : • exécutable : julia ; • arguments : %{CurrentDocument:FilePath} ; • répertoire de travail : %{CurrentDocument:Path} . L’exécution du fichier par Julia est accessible dans le menu Outils/Externe. On pourra créer un raccourci clavier... Une coloration syntaxique est disponible à télécharger depuis Outils/Options/ Éditeur de texte/Coloration syntaxique générique. Pour finir, on peut aussi utiliser un notebook : IJulia. Pour ce faire, exécuter les commandes suivantes dans un terminal : julia julia> Pkg.add("IJulia") julia> using IJulia julia> notebook() La deuxième commande sert à charger le module IJulia, il est donc inutile de la lancer à chaque fois... Le navigateur par défaut s’ouvre sous l’environnement Jupyter (comme IPython), très simple à utiliser. 3 [email protected] 3. Structures usuelles Boucles, conditionnement Données 4 [email protected] 4. Matrices Définition C’est direct : julia> A=[1 2 3 ; 4 5 6 ; 7 8 7] 3x3 1 2 4 5 7 8 Array{Int64,2}: 3 6 7 Ici 3x3 Array{Int64,2} signifie que A est un tableau d’entiers à deux dimensions, de taille 3×3. On peut donner la taille de A par : julia> size(A) (3,3) Extraire un élément, une ligne ou une colonne Les indices débutent à 1, à la différence de Python (entre autres...) : julia> A[2,1] 4 Les slices sont bien sûr utilisables plus finement que dans ce qui suit... julia> A[2,:] 1x3 Array{Int64,2}: 4 5 6 julia> A[:,3] 3-element Array{Int64,1}: 3 6 7 5 [email protected] Opérations Les sommes, différences ou produits s’effectuent très naturellement. Une puissance aussi : julia> Aˆ2015 3x3 Array{Int64,2}: 1583313351890381144 -7279767086941224252 -5146998712661124592 -6486402176729027370 -3167002905664645007 -7993517345919539836 7203907103967830684 -1818064437605062198 6654452081578112168 Les opérations élément par élément sont possibles (même chose pour +, − ou /) : julia> 2*A 3x3 Array{Int64,2}: 2 4 6 8 10 12 14 16 14 Pour la puissance élément par élément : julia> A.ˆ2 3x3 Array{Int64,2}: 1 4 9 16 25 36 49 64 49 Le point avant la commande indique de traiter élément par élément. Par exemple : julia> A.>3 3x3 BitArray{2}: false false false true true true true true true L’exponentielle d’une matrice : julia> exp(A) 3x3 Array{Float64,2}: 2.71828 7.38906 20.0855 54.5982 148.413 403.429 1096.63 2980.96 1096.63 6 [email protected] La transposée d’une matrice : julia> A’ 3x3 1 4 2 5 3 6 Array{Int64,2}: 7 8 7 Inversion et équations On peut inverser A par la commande inv(A) ou classiquement par : julia> Aˆ(-1) 3x3 Array{Float64,2}: -2.16667 1.66667 -0.5 2.33333 -2.33333 1.0 -0.5 1.0 -0.5 On peut trouver X telle que A*X=B : julia> B=[3 ; 2 ; 1] 3-element Array{Int64,1}: 3 2 1 julia> X=A\B 3-element Array{Float64,1}: -3.66667 3.33333 -6.66134e-16 Vu que la syntaxe est étrange, on peut songer à vérifier : julia> inv(A)*B 3-element Array{Float64,1}: -3.66667 3.33333 -6.10623e-16 7 [email protected] Prions pour qu’aucun élève ne dise qu’on a obtenu deux résultats différents... Si c’est le cas alors on pourra lui expliquer que le backslash est plus efficace car il provoque la résolution directe de l’équation A*X=B, au lieu de trouver Aˆ(-1) puis d’en faire le produit avec B . Le gain est double : en temps d’exécution et en précision. Matrices utiles Une matrice identité : julia> eye(3) 3x3 1.0 0.0 0.0 Array{Float64,2}: 0.0 0.0 1.0 0.0 0.0 1.0 Une matrice diagonale : julia> diagm([3,5,7]) 3x3 3 0 0 5 0 0 Array{Int64,2}: 0 0 7 Une matrice aléatoire : julia> rand(3,3) 3x3 Array{Float64,2}: 0.869429 0.0627175 0.718558 0.146539 0.0164233 0.0416191 0.510512 0.89997 0.788979 Une matrice nulle : julia> zeros(3,3) 3x3 0.0 0.0 0.0 Array{Float64,2}: 0.0 0.0 0.0 0.0 0.0 0.0 8 [email protected] Diagonalisation Julia retourne par eig(A) un 2-tuple constitué d’un tableau des valeurs propres suivi d’une matrice de vecteurs propres. Ainsi : julia> P=eig(A)[2] 3x3 Array{Float64,2}: -0.248828 -0.571836 0.595561 -0.568631 -0.327291 -0.758896 -0.784056 0.752252 0.263408 julia> D=Pˆ(-1)*A*P 3x3 Array{Float64,2}: 15.0235 1.77636e-15 -6.21725e-15 -4.10783e-15 -1.80181 1.66533e-16 4.05925e-15 -1.29063e-15 -0.221653 On peut alors jouer : julia> Aˆ7 3x3 Array{Int64,2}: 21834720 26969076 28331784 49897542 61630737 64744788 68801236 84979514 89273248 julia> P*D.ˆ7*Pˆ(-1) 3x3 Array{Float64,2}: 2.18347e7 2.69691e7 2.83318e7 4.98975e7 6.16307e7 6.47448e7 6.88012e7 8.49795e7 8.92732e7 Notons que le résultat donné est identique sans tricher, c’est-à-dire avec Dˆ7 au lieu de D.ˆ7 . 9 [email protected] 5. Nombres complexes Généralités Le nombre i se note im . On peut écrire indifféremment 1+2*im ou 1+2im . Il semble clair que la seconde option est peu habituelle et limitée lorsqu’on a affaire à une variable au lieu de 2 . Les opérations s’écrivent naturellement. Les fonctions de base sont : julia> z=1+sqrt(3)*im 1.0 + 1.7320508075688772im julia> real(z), imag(z), conj(z) (1.0,1.7320508075688772,1.0 - 1.7320508075688772im) julia> abs(z) 1.9999999999999998 julia> abs2(z) 3.9999999999999996 julia> angle(z) 1.0471975511965976 julia> ans*180/pi 59.99999999999999 Le premier élève qui se plaindra des approximations sera puni. À propos de punition, Julia n’est pas toujours bienveillant (quoique...) : julia> sqrt(-1) ERROR: DomainError Ensemble de Mandelbrot L’utilisation de la bibliothèque graphique Cairo a été introduite dans un chapitre précédent. # module de dessin using Cairo 10 [email protected] # calcul du nombre d’itérations function iter(z,maxiter) c = z for n = 1:maxiter if abs(z) > 2 return n-1 end z = z*z + c end return maxiter end # fonction principale function mandelbrot() maxiter = 80 xmin = -2 xmax = 2 ymin = -2 ymax = 2 pas = 0.0005 pixels = 768 xdelta = pixels/(xmax-xmin) ydelta = pixels/(ymax-ymin) c = CairoRGBSurface(pixels,pixels) cr = CairoContext(c) save(cr) set_source_rgb(cr,0.9,0.9,0.9) rectangle(cr,0,0,pixels,pixels) fill(cr) restore(cr) save(cr) for x = xmin:pas:xmax for y = ymin:pas:ymax rouge = max(1-2*iter(x+y*im,maxiter)/maxiter,0) vert = rouge bleu = rouge xcoord = pixels/2+x*xdelta ycoord = pixels/2-y*ydelta set_source_rgb(cr, rouge, vert, bleu) move_to(cr, xcoord, ycoord) line_to(cr, xcoord+0.1, ycoord+0.1) stroke(cr) end end restore(cr) write_to_png(c,"mandelbrot.png") end mandelbrot() 11 [email protected] 6. Arithmétique Fonctions courantes Elles sont présentes nativement dans Julia : julia> 2015%7, mod(2015,7), gcd(2016,35), lcm(2016,35) (6,6,7,10080) Ce qui touche au théorème de Bézout est aussi disponible : julia> gcdx(2015,7) (1,-1,288) julia> 2015*(-1)+7*288 1 julia> invmod(7,2015) 288 Concernant les nombres premiers et la factorisation : julia> isprime(68), isprime(97) (false,true) julia> factor(123456789) Dict{Int64,Int64} with 3 entries: 3 => 2 3803 => 1 3607 => 1 On notera que Julia donne ici le résultat sous forme de dictionnaire associant un nombre premier et sa puissance dans la décomposition. julia> primes(100) 25-element ArrayInt64,1: 2 3 5 12 [email protected] . . . 97 Un exemple de chiffrement RSA Vu que c’est un peu le but à atteindre en spécialité Mathématiques, allons-y : julia> e=3; p=41; q=53; k=(p-1)*(q-1); n=p*q; d=invmod(e,k) 1387 julia> mot=2015 2015 julia> motChiffr=powermod(mot,e,n) 1856 julia> motDechiffr=powermod(motChiffr,d,n) 2015 13 [email protected]