Nota G [a] es un algoritmo informático escrito por Ada Lovelace que fue diseñado para calcular números de Bernoulli utilizando el motor analítico hipotético . En general, se acepta que la Nota G es el primer algoritmo específico para una computadora, [1] [2] [3] [4] y, como resultado, Lovelace es considerada la primera programadora de computadoras . [5] [6] [7] [8] El algoritmo fue la última nota de una serie etiquetada de la A a la G, que utilizó como ayuda visual para acompañar su traducción al inglés de la transcripción francesa de 1842 de Luigi Menabrea de la conferencia de Charles Babbage sobre el motor analítico en la Universidad de Turín , "Notions sur la machine analytique de Charles Babbage" ("Elementos de la máquina analítica de Charles Babbage"). [7] [9] La Nota G de Lovelace nunca se probó, ya que el motor nunca se construyó. Sus notas, junto con su traducción, se publicaron en 1843. [6] [7]
En la era moderna , gracias a la disponibilidad de equipos informáticos y recursos de programación más accesibles, el algoritmo de Lovelace ha sido probado, después de ser "traducido" a lenguajes de programación modernos. Estas pruebas han concluido de forma independiente que había un error en el script, debido a un pequeño error tipográfico, que hacía que el algoritmo en su estado original fuera inutilizable. [10] [11]
En 1840, Charles Babbage fue invitado a dar un seminario en Turín sobre su máquina analítica, [12] la única explicación pública que dio sobre la máquina. [13] Durante la conferencia de Babbage, el matemático Luigi Menabrea escribió un relato de la máquina en francés. [12] Un amigo de Babbage, Charles Wheatstone , sugirió que para contribuir, Lovelace debería traducir el relato de Menabrea. [12] [14] Babbage sugirió que ella ampliara el relato con apéndices, que compiló al final de su traducción como una serie de siete "notas" etiquetadas como AG. Su traducción se publicó en agosto de 1843, [12] en Taylor's Scientific Memoirs , [14] [15] donde el nombre de Lovelace estaba firmado "AAL". [12] [b] En estas notas, Lovelace describió las capacidades del motor analítico de Babbage si se utilizara para computación, y trazó un plan para el motor más ambicioso que el que el propio Babbage tenía. [3] [15] [16]
Las notas de Lovelace para el artículo eran tres veces más largas que el artículo mismo. [17] En las primeras notas, explora más allá de las ambiciones numéricas que Babbage tenía para la máquina, y sugiere que la máquina podría aprovechar la computación para lidiar con los reinos de la música, los gráficos [18] y el lenguaje. [8] [19] [20]
Además, podría actuar sobre otras cosas además del número, si se encontraran objetos cuyas relaciones fundamentales mutuas pudieran expresarse mediante las de la ciencia abstracta de las operaciones, y que también fueran susceptibles de adaptaciones a la acción de la notación operativa y del mecanismo de la máquina. Suponiendo, por ejemplo, que las relaciones fundamentales de los sonidos afinados en la ciencia de la armonía y de la composición musical fueran susceptibles de tal expresión y adaptaciones, la máquina podría componer piezas musicales elaboradas y científicas de cualquier grado de complejidad o extensión.
— Ada Lovelace, Notas sobre las memorias "Bosquejo de la máquina analítica inventada por Charles Babbage" de la traductora Ada Augusta, condesa de Lovelace, Nota A
Lovelace explica a los lectores cómo el motor analítico estaba separado del motor diferencial anterior de Babbage , [21] y compara su función con la máquina Jacquard , [22] en que usaba tarjetas perforadas binarias para denotar el lenguaje de la máquina . En la nota C, este punto se ve reforzado por el hecho de que la máquina puede realizar acciones simultáneas e iteradas , lo que garantiza que cualquier tarjeta o conjunto de tarjetas se pueda usar varias veces en la solución de un solo problema, [20] anticipando esencialmente los métodos modernos de flujo de control y bucle. [17] [23] Estas ideas se llevaron a un punto crítico en la nota final, G, donde Lovelace buscó demostrar un ejemplo de computación .
La nota G sólo hizo uso de las cuatro operaciones aritméticas : suma, resta, multiplicación y división, la implementación de la visión de Babbage:
Ante la imposibilidad de explicar aquí el proceso por el cual se alcanza este fin, debemos limitarnos a admitir que las cuatro primeras operaciones de la aritmética, es decir, la suma, la resta, la multiplicación y la división, pueden realizarse de manera directa mediante la intervención de la máquina. Supuesto esto, la máquina es, por tanto, capaz de realizar toda clase de cálculos numéricos, pues todos estos cálculos se reducen, en última instancia, a las cuatro operaciones que acabamos de nombrar.
— Charles Babbage, "Esbozo de la máquina analítica inventada por Charles Babbage"
También utiliza la idea de Babbage de almacenar información en columnas de discos, cada uno denotado por (para la variable ) y un número subíndice que indica a qué columna se hace referencia.
Lovelace utilizó una ecuación recursiva para calcular los números de Bernoulli, [12] en la que utilizó los valores anteriores de una ecuación para generar la siguiente. Su método funcionaba así: [24]
donde es un coeficiente binomial ,
Los números de Bernoulli se pueden calcular de muchas maneras , pero Lovelace eligió deliberadamente un método elaborado para demostrar el poder de la máquina. En la Nota G, afirma: "Terminaremos estas Notas siguiendo en detalle los pasos a través de los cuales la máquina pudo calcular los Números de Bernoulli, siendo este (en la forma en que lo deduciremos) un ejemplo bastante complicado de sus poderes". [20] El algoritmo particular utilizado por Lovelace en la Nota G genera el octavo número de Bernoulli (etiquetado como , ya que comenzó con .) [24]
La tabla del algoritmo organiza cada comando en orden. Cada comando denota una operación que se realiza sobre dos términos. La segunda columna indica únicamente el operador que se utiliza. Las variables se anotan como " ", [c] donde el superíndice anterior representa la cantidad de valores diferentes a los que se ha asignado la variable y el subíndice posterior representa la asignación ordinal de la variable, es decir, de qué variable se trata. (Por ejemplo, se refiere a la segunda asignación de la variable número 4. Cualquier variable hasta ahora no definida tiene un superíndice de 0). Las variables se numeran a partir de . La tercera columna le dice al ordenador exactamente qué comando se está ejecutando (por ejemplo, en la línea 1, el comando realizado es " " - la primera iteración de la variable 2 se multiplica por la primera iteración de la variable 3) y solo incorpora una operación entre dos términos por línea. La columna 4 - "Variables que reciben resultados" toma nota de dónde se debe almacenar el resultado de la operación en la columna 3. De esta manera, cualquier variable en esta columna tiene su número superíndice incrementado en uno cada vez. (por ejemplo, en la línea 1, el resultado de se asigna a las variables , , y ).
La columna 5 indica si se ha modificado alguna de las variables utilizadas en la operación del comando. Encerradas entre llaves, dos filas por comando colocan la variable original en el lado izquierdo de un signo igual y la nueva variable en el otro lado; es decir, si se ha modificado la variable, su superíndice se incrementa en uno y, si no, permanece igual. (p. ej., la línea tres asigna el resultado de a la segunda iteración de la variable , y la quinta columna lo refleja indicando;
Ha cambiado, pero no ha cambiado.
En la columna 6, "Declaración de resultados", el resultado asignado a la variable en la columna 4 se muestra en su valor exacto basado en los valores de los dos términos asignados previamente. (p. ej. en la línea 1 - - se estableció al principio como , y se estableció como la variable . Por lo tanto, , en notación matemática .) Esta columna aparentemente no es calculada por el motor, y parece ser más para ayudar a la claridad y la capacidad del lector para seguir los pasos del programa. (Por ejemplo, la línea 5 tiene una fracción que se divide por dos, que se anota como si se multiplicara por la mitad, probablemente por coherencia y la complejidad tipográfica de una fracción anidada). También hace uso de una notación de variable separada fuera del programa, las variables y , que se multiplican sucesivamente para encontrar el valor final, , por lo tanto: [10]
Más allá de esto, cada columna sucesiva muestra los valores de una variable dada a lo largo del tiempo. Cada vez que una variable cambia, o su valor se vuelve relevante por su presencia como uno de los términos en el comando actual, su valor se indica o se reafirma en su columna respectiva. De lo contrario, se marca con puntos suspensivos para indicar su irrelevancia. Esto presumiblemente imita la necesidad de la computadora de solo información relevante, rastreando así el valor de una variable a medida que el programa analiza . [10]
El programa buscaba calcular lo que la convención moderna conoce como el octavo número de Bernoulli, que aparece como , cuando Lovelace comienza a contar desde . [24]
En la operación 4, la división que supuestamente se está realizando es " ", que se almacenará en la variable . Sin embargo, el "Estado de resultados" dice que la división debería ser:
De hecho, la división está al revés; es la segunda iteración de , como se puede ver en la operación 2. Asimismo, es la segunda iteración de , como se puede ver en la operación 3. Por lo tanto, la operación 4 no debería ser , sino . Este error significa que si el motor alguna vez ejecutara este algoritmo en este estado, no generaría números de Bernoulli correctamente y encontraría que su valor objetivo final ( el octavo número de Bernoulli, ) es .
El programa de Lovelace se puede implementar en un lenguaje de programación moderno , aunque debido al error mencionado anteriormente, si se transcribiera exactamente devolvería un valor final incorrecto para . El programa original generalizado en pseudocódigo es el siguiente:
V[1] = 1V[2] = 2V[3] = n (n = 4 en el programa de Lovelace).V[4] = V[4] - V[1]V[5] = V[5] + V[1]V[11] = V[5] / V[4]V[11] = V[11] / V[2]V[13] = V[13] - V[11]V[10] = V[3] - V[1]V[7] = V[2] + V[7]V[11] = V[6] / V[7]V[12] = V[21] * V[11]V[13] = V[12] + V[13]V[10] = V[10] - V[1]V[6] = V[6] - V[1]V[7]= V[1] + V[7]//Terminar más tarde
La implementación en pseudocódigo resalta el hecho de que los lenguajes de programación definen variables en una pila , lo que obvia la necesidad de rastrear y especificar la iteración actual de una variable. Además, el programa de Lovelace solo permitía definir variables realizando una suma , resta , multiplicación o división en dos términos que previamente eran variables definidas. La sintaxis moderna sería capaz de realizar cada cálculo de manera más concisa. Esta restricción se hace evidente en algunos lugares, por ejemplo en el comando 6 ( ). Aquí Lovelace define una variable hasta ahora indefinida ( ) por sí misma, asumiendo así que todas las variables indefinidas son automáticamente iguales a 0, donde la mayoría de los lenguajes de programación modernos devolverían un error o enumerarían la variable como null . Lo que pretendía era " ", pero se había limitado a usar solo variables como términos. Del mismo modo, en el comando 8 ( ), la notación estricta de la aritmética de dos términos se vuelve engorrosa, ya que para definir como 2, Lovelace asigna su valor (0) a sí mismo más (2). Es debido a esta notación restrictiva que se define así.