Búsqueda

He utilizado MATLAB durante más de 25 años. (Y antes de eso, incluso utilicé MATRIXx, un intento tardío y no lamentable de spinoff, o quizás un ripoff). No es el primer lenguaje en el que aprendí a programar, pero es con el que alcancé la mayoría de edad matemática. Conocer MATLAB ha sido muy bueno para mi carrera.

Sin embargo, es imposible ignorar el ascenso de Python en la computación científica. MathWorks debe sentir lo mismo: no sólo han añadido la posibilidad de llamar a Python directamente desde MATLAB, sino que han adoptado prestadas algunas de sus características del lenguaje, como una emisión más agresiva para los operandos de los operadores binarios.

Ha llegado un punto en el que he estado cuestionando mi uso continuado de MATLAB tanto en la investigación como en la enseñanza. Sin embargo, me resulta tan fácil utilizarlo, y he invertido tanto en materiales para ello, que era difícil reunir la motivación para aprender realmente algo nuevo.

Entre el libro de texto basado en MATLAB que he coescrito para la introducción a las matemáticas computacionales. El libro tiene más de 40 funciones y 160 ejemplos computacionales, y cubre lo que creo que es una base completa en el uso de MATLAB para la computación científica numérica. Así que, en parte para mejorar, y en parte para aumentar la utilidad del libro, me propuse este año traducir los códigos a Julia y Python. Esta experiencia me ha llevado a tener una perspectiva particular sobre los tres lenguajes en relación con la computación científica, que intento plasmar a continuación.

Dejaré de lado principalmente las cuestiones de coste y apertura. MATLAB, a diferencia de Python y Julia, no es ni libre de cerveza ni libre de discurso. Esta es, de hecho, una gran distinción-para algunos, una dispositiva-pero quiero considerar los méritos técnicos. Durante muchos años, MATLAB estuvo muy por encima de cualquier producto gratuito en una serie de aspectos muy útiles, y si querías ser productivo, al diablo con el coste. Es una consideración aparte del atractivo platónico de un lenguaje y un ecosistema.

Cuando se deja de lado el coste, un marco útil para muchas de las diferencias entre estos lenguajes reside en sus orígenes. MATLAB, el más antiguo de todos, dio prioridad a las matemáticas, especialmente a las orientadas al cálculo. Python, que comenzó en serio a finales de la década de 1980, hizo de la informática su objetivo central. Julia, que comenzó en 2009, se propuso lograr un mayor equilibrio entre estos lados.

MATLAB

Originalmente, cada valor en MATLAB era una matriz de números de punto flotante de doble precisión. Ambos aspectos de esta elección, las matrices y el punto flotante, fueron decisiones de diseño inspiradas.

El estándar IEEE 754 para el punto flotante no se adoptó hasta 1985, y la memoria se medía en K, no en G. Los dobles de punto flotante no eran la forma más eficiente de representar caracteres o enteros, pero eran lo que los científicos, ingenieros y, cada vez más, los matemáticos querían utilizar la mayor parte del tiempo. Además, las variables no tenían que declararse y la memoria no tenía que asignarse explícitamente. Dejar que el ordenador se encargara de esas tareas y eliminar los tipos de datos liberaba el cerebro para pensar en los algoritmos que operarían con los datos.

Las matrices eran importantes porque los algoritmos numéricos del álgebra lineal estaban llegando a su fin, en forma de LINPACK y EISPACK. Pero acceder a ellos con el portador estándar de la computación científica, FORTRAN 77, era un proceso de varios pasos que implicaba declarar variables, llamar a rutinas con nombres crípticos, compilar el código y luego examinar los datos y los archivos de salida. Escribir una multiplicación de matrices como A*B y obtener la respuesta impresa de inmediato fue un cambio de juego.

MATLAB también hizo que los gráficos fueran fáciles y mucho más accesibles. No hay librerías específicas de la máquina con llamadas de bajo nivel, sólo plot(x,y) y se ve más o menos lo que cualquier otra persona con MATLAB vería. Hubo más innovaciones, como la incorporación de números complejos, matrices dispersas, herramientas para construir interfaces gráficas de usuario multiplataforma, y un conjunto de vanguardia de solucionadores de EDO, que hicieron de MATLAB el lugar para hacer la computación científica a la velocidad del pensamiento.

Sin embargo, el diseño que era ideal para los cálculos interactivos, incluso los más largos, no siempre era propicio para escribir un software bueno y eficiente. Mover datos entre muchas funciones requería hacer malabares con muchas variables y consultar frecuentemente la documentación sobre los argumentos de entrada y salida. Una función por archivo de disco en un espacio de nombres plano era refrescantemente simple para un proyecto pequeño, pero un dolor de cabeza para uno grande. Había que aplicar ciertos patrones de programación (vectorización, preasignación de memoria) si se quería evitar los cuellos de botella de velocidad. La computación científica se aplicaba ahora a muchos más dominios, con enormes cantidades de datos de diferentes tipos nativos. Etc.

MathWorks respondió continuando la innovación dentro de MATLAB: funciones en línea, funciones anidadas, cierres de variables, numerosos tipos de datos, características orientadas a objetos, marcos de pruebas unitarias, y así sucesivamente. Cada innovación era probablemente la solución a un problema importante. Pero la acumulación de 40 años de estos cambios ha tenido el efecto secundario de erosionar la simplicidad y la unidad de concepto. En 2009 escribí un libro que cubría bastante bien lo que yo consideraba lo esencial de MATLAB en menos de 100 páginas. Que yo sepa, todo eso sigue estando disponible. Pero necesitas saber mucho más ahora para considerarte competente.

Python

En cierto sentido, la historia de Python parece ser casi un espejo de la de MATLAB. Ambos contaban con una línea de comandos interactiva (ahora ampliamente llamada REPL, por «read-eval-print loop») y libertad de declaraciones de variables y compilación. Pero MATLAB se creó como patio de recreo para los analistas numéricos, mientras que Python se creó pensando en los hackers. Cada uno creció luego hacia la otra audiencia a través de revisiones y extensiones.

A mi parecer, Python aún carece de atractivo matemático. Tiene fealdad y pequeñas molestias como ** en lugar de ^, @ para la multiplicación de matrices (¡una innovación reciente!), un shape en lugar del tamaño de una matriz, almacenamiento orientado a filas, etc. Si crees que V.conj().T@D**3@V es una forma elegante de escribir $V^*D^3V$, entonces puede que necesites ver a un médico. Y existe la indexación cero (a diferencia de los índices que comienzan en 1). He leído los argumentos y no los encuentro decisivos. Está claro que es una cuestión de preferencias -el material de las guerras santas en línea- porque se pueden citar ejemplos poco convincentes para cualquiera de las dos convenciones. Lo que encuentro decisivo es que tenemos décadas de práctica matemática indexando vectores y matrices a partir de uno, y la mayoría del pseudocódigo hace esa suposición.

Más allá de las pequeñas molestias, encuentro que el ecosistema Python+NumPy+SciPy es torpe e inconsistente. Un ejemplo es el hecho de que a pesar de que el lenguaje es bastante dedicado a la orientación a objetos, existe una clase matriz, y sin embargo, su uso se desaconseja y será obsoleto. Quizás MATLAB simplemente me ha corrompido, pero encuentro que las matrices son un tipo de objeto lo suficientemente importante como para mantenerlo y promoverlo. ¿No es uno de los principales puntos de venta de la programación orientada a objetos el hecho de que puedas tener * cosas diferentes para arrays y matrices? Hay muchas otras infelicidades en este sentido. (¿Por qué necesito un comando llamado spsolve? ¿No puedo simplemente llamar a solve en una matriz dispersa? Y así sucesivamente.)

También hay lugares en los que el ecosistema numérico me parece un poco escaso. Por ejemplo, los solucionadores de cuadratura y ODE parecen un conjunto mínimo en 2019. AFAICT no hay métodos para DAEs, DDEs, solucionadores simplécticos, o solucionadores implícitos que permiten iteraciones internas de Krylov. Echa un vistazo a las referencias de estas funciones; en su mayoría tienen 30 o más años de antigüedad; siguen siendo buenas, pero están muy lejos de ser completas. El paquete Matplotlib es un trabajo asombroso, y durante un tiempo parecía mejor que MATLAB, pero lo encuentro bastante carente de 3D todavía.

Algunos expertos argumentan que hay razones profundas por las que el código de Python lucha por mantener la velocidad de ejecución con los lenguajes compilados. Me hacen gracia los resultados de la búsqueda «python es demasiado lento». Los defensores de Python presentan muchos de los mismos argumentos/disculpas que la gente hizo por MATLAB en su día. Eso no significa que estén equivocados, pero hay algo más que un problema de percepción.

Creo que entiendo por qué Python ha sido tan emocionante para mucha gente en la computación científica. Tiene una sintaxis y potencia parecida a la de MATLAB, disponible desde un REPL. Tiene grandes herramientas a su alrededor y juega bien con otros lenguajes y áreas de la computación. Ofrece todo esto sin coste alguno y con una reproducibilidad a largo plazo mucho mayor. Claramente, funciona bien para mucha gente que probablemente ve pocas razones para cambiar.

Pero para las cosas que sé hacer en computación científica, Python se siente mucho más como una tarea para aprender y usar de lo que estoy acostumbrado. No sabremos hasta dentro de un tiempo si seguirá arrasando en la comunidad o si ya se ha acercado a su punto álgido. No tengo poderes especiales de predicción, pero soy bajista.

Julia

Julia tiene las ventajas y desventajas de ser un recién llegado. Aplaudo a los creadores de Julia por pensar que podían hacerlo mejor:

Queremos un lenguaje que sea de código abierto, con una licencia liberal. Queremos la velocidad de C con el dinamismo de Ruby. Queremos un lenguaje que sea homoicónico, con verdaderas macros como Lisp, pero con una notación matemática obvia y familiar como Matlab. Queremos algo tan útil para la programación general como Python, tan fácil para la estadística como R, tan natural para el procesamiento de cadenas como Perl, tan potente para el álgebra lineal como Matlab, tan bueno para pegar programas como el shell. Algo que sea sencillísimo de aprender, pero que mantenga contentos a los hackers más serios. Lo queremos interactivo y lo queremos compilado.

En gran medida, creo que lo han conseguido. A finales del camino hacia la versión 1.0 parecían restar importancia a la REPL un poco, y hubo algunos bandazos casi gratuitos lejos de MATLAB. (¿Cómo es exactamente LinRange mejor que linspace?) Estos son quibbles, sin embargo.

Este es el primer lenguaje que he utilizado que va más allá de ASCII. Todavía me satisface mucho usar variables como ϕ y operadores como . Es más que cosmético; ser capaz de parecerse más a las expresiones matemáticas que escribimos es una verdadera ventaja, aunque complica un poco la enseñanza y la documentación.

Trabajar en Julia me expuso que adquirí algunos hábitos de programación debido a las opciones de MATLAB, no a una superioridad inherente. La vectorización no es natural para muchas cosas. Es revelador descubrir en Julia que puedes vectorizar cualquier función simplemente añadiendo un punto a su nombre. Construir una matriz a través de una comprensión hace que los bucles anidados (o los trucos de meshgrid) parezcan látigos con errores en comparación, y evitar una matriz por completo a través de un generador para una simple suma se siente como obtener algo por nada. (Soy consciente de que Python tiene características de lenguaje similares.)

La gran característica del envío múltiple hace algunas cosas mucho más fáciles y claras que la orientación a objetos. Por ejemplo, supón que tienes las clases Wall y Ball en un lenguaje tradicional orientado a objetos. ¿Qué clase debería detectar una colisión de una Bola con una Pared? ¿O necesita una clase Habitación para hacer de árbitro? Este tipo de preguntas puede llevarme a la distracción. Con el envío múltiple, los datos se empaquetan en tipos de objetos, pero los métodos que operan sobre los datos no están vinculados a una clase. Así que

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

conoce los tipos pero se define independientemente de ellos. Me ha costado bastante programar para apreciar lo interesante y potencialmente importante que es la noción de envío múltiple para extender el lenguaje.

El ecosistema numérico ha ido evolucionando rápidamente. Mi ejemplo número uno es DifferentialEquations.jl, escrito por el increíble Chris Rackauckas. Si este software no gana pronto el premio Wilkinson, el sistema está roto. Sólo tienes que ir al sitio y prepararte para ser convertido.

Todavía no he visto las grandes ganancias de velocidad sobre MATLAB que promete Julia. En parte es mi relativa inexperiencia y el tipo de tareas que hago, pero también es en parte porque MathWorks ha hecho un trabajo increíble optimizando automáticamente el código. No es un aspecto de la codificación en el que me centre la mayor parte del tiempo, de todos modos.

Programar en Julia me ha llevado un tiempo para sentirme cómodo (tal vez sólo estoy envejeciendo y cristalizado). Me hace pensar en los tipos de datos más de lo que querría, y siempre existe la sospecha furtiva de que me he perdido la forma correcta de hacer algo. Pero para el uso diario, soy tan propenso a recurrir a Julia como a MATLAB ahora.

La conclusión

MATLAB es la solución corporativa, especialmente para la ingeniería. Es probablemente todavía el más fácil de aprender para las tareas numéricas básicas. Una documentación meticulosa y décadas de herramientas de aprendizaje contribuidas definitivamente importan.

MATLAB es el BMW sedán del mundo de la computación científica. Es caro, y eso es antes de empezar a hablar de los accesorios (cajas de herramientas). Estás pagando por un rendimiento y un servicio sólidos como una roca. También atrae una cantidad desproporcionada de odio.

Python es una camioneta Ford. Es omnipresente y amado por muchos (en EEUU). Puede hacer todo lo que quieras, y está construido para hacer algunas cosas que otros vehículos no pueden. Lo más probable es que quieras tomar uno prestado de vez en cuando. Pero no ofrece una gran experiencia de conducción pura.

Julia es un Tesla. Está construido con el audaz objetivo de cambiar el futuro, y puede que lo haga. También puede llegar a ser sólo una nota a pie de página. Pero mientras tanto, llegará a su destino con estilo y con potencia de sobra.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.