Search

Am folosit MATLAB timp de peste 25 de ani. (Și înainte de asta, am folosit chiar și MATRIXx, o tentativă târzie și nefericită de spinoff, sau poate o ripoff). Nu este primul limbaj în care am învățat să programez, dar este cel cu care am ajuns la maturitate din punct de vedere matematic. Cunoașterea MATLAB a fost foarte bună pentru cariera mea.

Cu toate acestea, este imposibil să ignorăm ascensiunea lui Python în calculul științific. MathWorks trebuie să fie de aceeași părere: nu numai că au adăugat posibilitatea de a apela Python direct din MATLAB, dar au adoptat împrumutat unele dintre caracteristicile limbajului său, cum ar fi difuzarea mai agresivă pentru operanzii operatorilor binari.

Am ajuns la un punct în care am pus sub semnul întrebării utilizarea mea continuă a MATLAB atât în cercetare, cât și în predare. Cu toate acestea, atât de multe îmi vin cu ușurință acolo și am investit atât de mult în materiale pentru el, încât a fost greu să adun motivația pentru a învăța cu adevărat ceva nou.

Intrați în manualul bazat pe MATLAB pe care l-am co-scris pentru matematica computațională introductivă. Cartea are peste 40 de funcții și 160 de exemple de calcul și acoperă ceea ce eu consider că este o bază temeinică în utilizarea MATLAB pentru calculul științific numeric. Așadar, în parte pentru a mă autoperfecționa și în parte pentru a spori utilitatea cărții, mi-am propus anul acesta să traduc codurile în Julia și Python. Această experiență m-a condus la o perspectivă particulară asupra celor trei limbaje în legătură cu calculul științific, pe care încerc să o surprind mai jos.

În mare parte voi lăsa deoparte problemele legate de costuri și deschidere. MATLAB, spre deosebire de Python și Julia, nu este nici fără bere și nici fără discurs. Aceasta este într-adevăr o distincție uriașă – pentru unii, o distincție dispozitivă – dar vreau să iau în considerare meritele tehnice. Timp de mulți ani, MATLAB a depășit cu mult orice produs gratuit într-o serie de moduri extrem de utile, iar dacă voiai să fii productiv, atunci la naiba cu costurile. Este un considerent separat de atracția platonică a unui limbaj și a unui ecosistem.

Când lăsați costul deoparte, un cadru util pentru multe dintre diferențele dintre aceste limbaje se află în originile lor. MATLAB, cel mai vechi dintre eforturi, a prioritizat matematica, în special matematica orientată numeric. Python, care a început în mod serios la sfârșitul anilor 1980, a făcut din informatică punctul său central. Julia, care a început în 2009, și-a propus să găsească mai mult un echilibru între aceste laturi.

MATLAB

Original, fiecare valoare în MATLAB era o matrice de numere cu virgulă mobilă de precizie dublă. Ambele aspecte ale acestei alegeri, array-uri și virgulă flotantă, au fost decizii de proiectare inspirate.

Standardul IEEE 754 pentru virgulă flotantă nu a fost adoptat până în 1985, iar memoria era măsurată în K, nu în G. Dubla virgulă flotantă nu era cel mai eficient mod de a reprezenta caractere sau numere întregi, dar era ceea ce oamenii de știință, inginerii și, din ce în ce mai mult, matematicienii doreau să folosească în cea mai mare parte a timpului. În plus, variabilele nu trebuiau să fie declarate și memoria nu trebuia alocată în mod explicit. Lăsând computerul să se ocupe de aceste sarcini și dând la o parte tipurile de date, vă elibera creierul pentru a vă gândi la algoritmii care urmau să opereze asupra datelor.

Array-urile erau importante deoarece algoritmii numerici din algebra liniară își făceau apariția, sub forma LINPACK și EISPACK. Dar accesarea lor cu ajutorul purtătorului standard al calculului științific, FORTRAN 77, era un proces în mai mulți pași care presupunea declararea variabilelor, apelarea unor rutine cu nume criptate, compilarea codului și apoi examinarea datelor și a fișierelor de ieșire. Scrierea unei înmulțiri matriciale ca A*B și obținerea imediată a răspunsului tipărit a fost o schimbare de joc.

MATLAB a făcut, de asemenea, grafica ușoară și mult mai accesibilă. Fără biblioteci dificile specifice mașinii cu apeluri de nivel scăzut, doar plot(x,y) și vedeai cam ceea ce ar fi văzut oricine altcineva cu MATLAB. Au existat și mai multe inovații, cum ar fi numere complexe încorporate, matrici rare, instrumente pentru a construi interfețe grafice cu utilizatorul pe mai multe platforme și o suită de vârf de rezolvatori ODE, care au făcut din MATLAB locul unde se poate face calcul științific cu viteza gândirii.

Cu toate acestea, designul care era ideal pentru calculele interactive, chiar și cele lungi, nu a fost întotdeauna propice pentru a scrie software bun și performant. Deplasarea datelor între mai multe funcții necesita jonglarea cu multe variabile și consultarea frecventă a documentației despre argumentele de intrare și ieșire. O singură funcție pentru fiecare fișier pe disc într-un spațiu de nume plat era răcoritor de simplu pentru un proiect mic, dar o bătaie de cap pentru unul mare. Anumite modele de programare (vectorizare, prealocarea memoriei) trebuiau aplicate dacă se dorea evitarea blocajelor de viteză. Calculul științific era acum aplicat la mult mai multe domenii, cu cantități uriașe de tipuri de date native diferite. Etc.

MathWorks a răspuns continuând să inoveze în cadrul MATLAB: funcții inline, funcții imbricate, închideri de variabile, numeroase tipuri de date, caracteristici orientate pe obiecte, cadre de testare a unităților și așa mai departe. Fiecare inovație a fost, probabil, soluția la o problemă importantă. Dar acumularea de 40 de ani a acestor schimbări a avut ca efect secundar erodarea simplității și a unității de concept. În 2009 am scris o carte care acoperea destul de bine ceea ce eu consideram a fi elementele esențiale ale MATLAB în mai puțin de 100 de pagini. Din câte știu eu, toate acele lucruri sunt încă disponibile. Dar trebuie să știi mult mai multe acum pentru a te numi competent.

Python

Într-un fel, istoria lui Python pare să fie aproape o imagine în oglindă a celei a lui MATLAB. Ambele prezentau o linie de comandă interactivă (numită acum pe scară largă REPL, de la „read-eval-print loop”, adică „buclă de citire-evaluare-imprimare”) și libertate față de declarațiile de variabile și compilare. Dar MATLAB a fost creat ca un loc de joacă pentru analiștii numerici, în timp ce Python a fost creat cu gândul la hackeri. Fiecare a crescut apoi spre celălalt public prin revizuiri și extensii.

Pentru ochii mei, Python încă nu are atractivitate matematică. Aveți urâțenie și mici neplăceri, cum ar fi ** în loc de ^, @ pentru înmulțirea matricelor (o inovație recentă!), un shape în loc de dimensiunea unei matrice, stocare orientată pe rânduri, etc. Dacă credeți că V.conj().T@D**3@V este o modalitate elegantă de a scrie $V^*D^3V$, atunci s-ar putea să aveți nevoie să consultați un medic. Și există indexarea zero (spre deosebire de indexările care încep de la 1). Am citit argumentele și nu mi se par decisive. Este în mod clar o chestiune de preferință – chestie de războaie sfinte online – pentru că se pot cita exemple năstrușnice pentru ambele convenții. Ceea ce mi se pare decisiv este faptul că avem zeci de ani de practică matematică de indexare a vectorilor și matricelor de la unu, iar majoritatea pseudocodurilor fac această presupunere.

Pe lângă micile neplăceri, consider că ecosistemul Python+NumPy+SciPy este kludgy și inconsistent. Proba A este faptul că, în ciuda faptului că, în ciuda faptului că limbajul este mai degrabă dedicat orientării pe obiecte, există o clasă matrice, și totuși utilizarea acesteia este descurajată și va fi depreciată. Poate că MATLAB m-a corupt pur și simplu, dar eu consider că matricele sunt un tip de obiect suficient de important pentru a fi păstrat și promovat. Nu este un punct de vânzare major al OOP faptul că poți avea * să faci lucruri diferite pentru matrici și matrici? Există multe alte neajunsuri în această privință. (De ce am nevoie de o comandă numită spsolve? Nu pot chema pur și simplu solve pe o matrice spartă? Și așa mai departe.)

Există, de asemenea, locuri în care ecosistemul numeric mi se pare puțin cam subțire. De exemplu, rezolvatoarele de cuadratură și ODE arată ca un set minim în 2019. AFAICT nu există metode pentru DAE, DDE, rezolvări simplectice sau rezolvări implicite care să permită iterații Krylov interioare. Aruncați o privire la referințele pentru aceste funcții; acestea sunt în mare parte vechi de 30 sau mai mulți ani – încă bune, dar foarte departe de a fi complete. Pachetul Matplotlib este o lucrare uimitoare și, pentru o vreme, a arătat mai bine decât MATLAB, dar mi se pare că încă îi lipsește destul de mult în 3D.

Cei mai mulți experți susțin că există motive profunde pentru care codul Python se luptă să țină pasul în viteza de execuție cu limbajele compilate. Sunt amuzat de rezultatele căutării „python este prea lent”. Campionii lui Python aduc multe dintre aceleași argumente/apologii pe care le aduceau oamenii pentru MATLAB în trecut. Asta nu înseamnă că se înșeală, dar există mai mult decât o problemă de percepție.

Cred că înțeleg de ce Python a fost atât de interesant pentru mulți oameni din calculul științific. Are o sintaxă și o putere asemănătoare cu cea a lui MATLAB, disponibilă de la un REPL. Are instrumente grozave în jurul său și se joacă bine cu alte limbaje și domenii de calcul. A oferit toate acestea fără costuri și cu o reproductibilitate pe termen lung mult mai bună. În mod clar, funcționează bine pentru o mulțime de oameni care, probabil, nu văd prea multe motive pentru a se schimba.

Dar pentru lucrurile pe care știu să le fac în calculul științific, Python se simte mult mai mult ca o corvoadă de învățat și folosit decât sunt obișnuit. Nu vom ști pentru o vreme dacă va continua să măture comunitatea sau dacă s-a apropiat deja de apogeu. Nu am puteri speciale de predicție, dar sunt pesimist.

Julia

Julia are avantajele și dezavantajele de a fi un întârziat. Îi aplaud pe creatorii Julia pentru că s-au gândit că pot face mai bine:

Vrem un limbaj care să fie open source, cu o licență liberală. Vrem viteza lui C cu dinamismul lui Ruby. Vrem un limbaj care să fie homoiconic, cu macros adevărate ca Lisp, dar cu notații matematice evidente și familiare ca Matlab. Vrem ceva la fel de utilizabil pentru programarea generală ca Python, la fel de ușor pentru statistică ca R, la fel de natural pentru procesarea șirurilor de caractere ca Perl, la fel de puternic pentru algebră liniară ca Matlab, la fel de bun la lipirea programelor ca shell-ul. Ceva care să fie simplu de învățat, dar care să-i facă fericiți pe cei mai serioși hackeri. Îl vrem interactiv și îl vrem compilat.

Într-o mare măsură, cred că au reușit. Târziu, pe drumul spre versiunea 1.0, au părut să minimalizeze puțin REPL-ul, și au existat unele îndepărtări aproape gratuite de MATLAB. (Cum anume este LinRange mai bun decât linspace?) Acestea sunt totuși niște chichițe.

Este primul limbaj pe care l-am folosit care merge dincolo de ASCII. Încă mai am o satisfacție nerezonabilă de la utilizarea variabilelor ca ϕ și a operatorilor ca . Este mai mult decât cosmetică; a putea arăta mai mult ca expresiile matematice pe care le scriem este un adevărat plus, deși complică puțin predarea și documentarea.

Lucrul în Julia mi-a expus faptul că am preluat unele obiceiuri de programare din cauza alegerilor din MATLAB, nu din cauza superiorității inerente. Vectorizarea nu este naturală pentru multe lucruri. Este revelator să descoperi în Julia că poți vectoriza orice funcție doar adăugând un punct la numele ei. Construirea unei matrice prin intermediul unei înțelegeri face ca buclele imbricate (sau trucurile meshgrid) să pară niște biciuri cu bug-uri în comparație, iar evitarea totală a unei matrice prin intermediul unui generator pentru o simplă însumare se simte ca și cum ai obține ceva pentru nimic. (Sunt conștient de faptul că Python are caracteristici de limbaj similare.)

Grea caracteristică a dispecerizării multiple face unele lucruri mult mai ușoare și mai clare decât o face orientarea pe obiecte. De exemplu, să presupunem că aveți clasele Wall și Ball într-un limbaj tradițional orientat pe obiecte. Care clasă ar trebui să detecteze o coliziune a unei mingi cu un perete? Sau aveți nevoie de o clasă Room pentru a juca rolul de arbitru? Aceste tipuri de întrebări mă pot face să mă pierd cu firea. Cu dispecerizarea multiplă, datele sunt împachetate în tipuri de obiecte, dar metodele care operează asupra datelor nu sunt legate de o clasă. Deci

function detect_collision(B::Ball,W::Wall)

cunoaște tipurile, dar este definită independent de acestea. Mi-a luat destul de mult timp de programare pentru a aprecia cât de interesantă și potențial importantă este noțiunea de expediere multiplă pentru extinderea limbajului.

Ecosistemul numeric a evoluat rapid. Exemplul meu numărul unu este DifferentialEquations.jl, scris de uimitorul Chris Rackauckas. Dacă acest software nu va câștiga în curând premiul Wilkinson, sistemul este stricat. Mergeți pe site și pregătiți-vă să fiți convertiți.

Încă nu am văzut marile creșteri de viteză față de MATLAB pe care le promite Julia. În parte este din cauza lipsei mele relative de experiență și a tipurilor de sarcini pe care le fac, dar și pentru că MathWorks a făcut o treabă incredibilă în optimizarea automată a codului. Oricum, nu este un aspect al codării pe care mă concentrez în cea mai mare parte a timpului.

Programarea în Julia mi-a luat ceva timp să mă simt confortabil (poate că doar îmbătrânesc și mă cristalizez). Mă face să mă gândesc la tipurile de date mai mult decât mi-aș dori și există întotdeauna suspiciunea furișată că am ratat modul corect de a face ceva. Dar pentru utilizarea de zi cu zi, este la fel de probabil să apelez la Julia ca și la MATLAB acum.

Soluția finală

MATLAB este soluția corporativă, în special pentru inginerie. Probabil că este încă cel mai ușor de învățat pentru sarcini numerice de bază. Documentația meticuloasă și zeci de ani de instrumente de învățare contribuită contează cu siguranță.

MATLAB este sedanul BMW al lumii calculului științific. Este scump, și asta înainte de a începe să vorbim despre accesorii (cutii de instrumente). Plătiți pentru o performanță și un serviciu solid ca o stâncă, fără probleme. Atrage, de asemenea, o cantitate disproporționată de ură.

Python este o camionetă Ford. Este omniprezent și iubit de mulți (în SUA). Poate face tot ce îți dorești și este construit pentru a face unele lucruri pe care alte vehicule nu le pot face. Sunt șanse să doriți să împrumutați unul din când în când. Dar nu oferă o experiență de condus pură și grozavă.

Julia este o Tesla. Este construită cu scopul îndrăzneț de a schimba viitorul și s-ar putea să o facă. De asemenea, ar putea deveni doar o notă de subsol. Dar, între timp, veți ajunge acolo unde vă duceți cu stil și cu putere de rezervă.

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.