L'alba della programmazione
di Mauro Murzi

In questo articolo è descritta la traduzione inglese, opera di Ada Lovelace nel 1843, di un lavoro pubblicato l'anno precedente dal matematico, ingegnere e all'epoca ufficiale del genio militare Luigi Menabrea. L'articolo di Menabrea e le note che Ada Lovelace aggiunse alla traduzione contengono alcuni tra i primi programmi per calcolatore pubblicati.

I due protagonisti.
Luigi Federico Menabrea (1809-1896) studiò ingegneria e matematica all'università di Torino; divenne quindi ufficiale del genio militare. immagineFu uno dei pochi studiosi che apprezzarono l'opera di Charles Babbage, alla quale dedicò un articolo pubblicato nel 1842 in lingua francese nella rivista Bibliothèque Universelle de Genève, contenente alcuni semplici esempi di programmi per calcolatore, forse i primi in assoluto ad essere pubblicati in una rivista scientifica. Nel 1843 l'articolo fu tradotto in inglese, con il titolo A Sketch of the Analytical Engine Invented by Charles Babbage, da Augusta Ada Lovelace, figlia del celebre poeta Lord Byron, e pubblicato nel volume 3 della rivista Scientific Memoirs edita da Richard e John Taylor. Nel 1848 Menabrea partecipò alla prima guerra di indipendenza come ufficiale del genio; nel 1859, durante la seconda guerra di indipendenza, aveva il comando del genio militare. Successivamente Menabrea intraprese con successo la carriera politica: fu ministro della marina e ministro dei lavori pubblici (1861-1864); nel 1866 fu nominato plenipotenziario per la firma del trattato di Praga che portò all'annessione di Venezia all'Italia; tra il 1867 e il 1869 fu primo ministro (durante il suo governo Giuseppe Garibaldi fu arrestato in seguito al fallito tentativo di liberazione di Roma, terminato con la sconfitta dei garibaldini a Mentana). In seguito fu ambasciatore a Londra e a Parigi. Nel 1870 pubblicò, in collaborazione con J. L. F. Bertrand, un importante contributo alla teoria della meccanica, concernente il principio del lavoro minimo; immaginein questo articolo è presentata quella che è ritenuta la prima dimostrazione corretta di tale principio.
Augusta Ada Lovelace (1815-1852), figlia di Lord Byron, nacque pochi mesi prima della separazione dei genitori. Fu affidata alla madre, che predilesse per lei l'istruzione matematico-scientifica al posto della più tradizionale istruzione letteraria. Nel 1834 Ada incontrò Charles Babbage. Nel 1835 sposò William King. Alcuni anni dopo William divenne conte di Lovelace e Ada assunse il titolo di contessa di Lovelace. Nel 1840 Ada iniziò un'attiva collaborazione con Babbage. Nel 1841 Babbage tenne a Torino un seminario avente per argomento l'Analytical Engine. L'anno seguente Luigi Menabrea scrisse l'articolo descrivente il progetto di Babbage che fu pubblicato nel 1842 nella rivista Bibliothèque Universelle de Genève. Ada ne curò la successiva traduzione in inglese. Nella sua autobiografia Babbage descrive così ciò che accadde.

Poco tempo dopo la comparsa della memoria [di Menabrea] nella "Bibliothèque Universelle de Genève", la Contessa di Lovelace mi informò che aveva tradotto la memoria di Menabrea. Le chiesi perché non aveva ella stessa scritto un lavoro originale su un soggetto del quale aveva una così intima conoscenza? A questa domanda Lady Lovelace rispose che tale idea non le era venuta in mente. Io allora suggerii che avrebbe potuto aggiungere alcune note alla memoria di Menabrea; un'idea che fu immediatamente adottata.
Discutemmo insieme i vari esempi che potevano essere introdotti: ne suggerii diversi, ma la scelta fu interamente sua. Suo fu anche il lavoro algebrico sui differenti problemi, eccettuato quello relativo ai numeri di Bernoulli, che mi ero offerto di fare per evitare a Lady Lovelace questa fatica. Tale lavoro mi fu rimandato indietro da lei per correzioni, poiché si era accorta di un grave errore che avevo commesso.
Le note della Contessa di Lovelace assommano a circa tre volte la lunghezza dell'articolo originario. L'autore è pienamente entrato in quasi tutti i più difficili e astratti problemi connessi con il soggetto.
Queste due memorie [quella di Menabrea e le note di Ada] prese insieme fornisco, a coloro che sono capaci di comprenderne il ragionamento, una dimostrazione completa che lo sviluppo e le operazioni dell'analisi posso adesso essere eseguiti dalla macchina. [Traduzione mia dall'originale inglese pubblicato in http://www-history.mcs.st-andrews.ac.uk/history/Mathematicians/Lovelace.html].

L'articolo di Menabrea.
immagineMenabrea descrive all'inizio dell'articolo il primo calcolatore progettato da Babbage e chiamato Difference Engine. In maniera sintetica ed efficace, Menabrea ne descrive il principio di funzionamento, le possibilità di applicazione pratica e le limitazioni intrinseche. Passando alla spiegazione dell'Analytical Engine, nato secondo Menabrea per superare le limitazioni del Difference Engine, Menabrea individua subito le sue caratteristiche fondamentali:

A questo punto Menabrea descrive le possibilità offerte dall'Analytical Engine. Per comprendere i successivi esempi di programmi offerti da Menabrea e da Ada Lovelace è necessario seguire la breve spiegazione che Menabrea fornisce dei principi di funzionamento di questo calcolatore. Ecco come Menabrea descrivere il metodo utilizzato nel calcolatore per rappresentare i numeri.

Immaginiamo una pila o una colonna verticale consistente di un numero indefinito di dischi circolari, tutti attraversati nei loro centri da un asse comune, attorno al quale ciascuno di essi può eseguire un movimento rotatorio indipendente. Se lungo il bordo di questi dischi sono scritte le dieci cifre che costituiscono il nostro alfabeto numerico, noi possiamo, disponendo opportunamente una serie di queste cifre nella stessa colonna, esprimere un qualsiasi numero. E' sufficiente a questo scopo che il primo disco rappresenti le unità, il secondo le decine, il terzo le centinaia, e così via. In genere, se abbiamo una serie di colonne di dischi, designate come V0, V1, V2, V3, V4, ecc., noi possiamo chiedere, per esempio, di dividere il numero scritto nella colonna V1 per quello nella colonna V4, e di ottenere il risultato nella colonna V7. [Questa citazione, come tutte le seguenti, è tratta da L. F. Menabrea, A Sketch of the Analytical Engine Invented by Charles Babbage, traduzione inglese e note di Ada Lovelace, reperibile in http://www.fourmilab.ch/babbage/sketch.html (traduzione italiana mia)].

Menabrea fa subito notare che per eseguire l'operazione di divisione appena descritta è necessario impartire due distinti ordini alla macchina:

attraverso il primo essa è predisposta per eseguire una divisione, e attraverso il secondo sono indicate le colonne sulle quali operare, e anche la colonna sulla quale rappresentare il risultato.

Ne consegue che

le disposizioni che devono essere comunicate alle varie parti della macchina possono essere distinte in due classi principali:
   Primo, quella relativa alle Operazioni.
   Secondo, quella relativa alle Variabili.

Le Operazioni indicano alla macchina quale delle quattro operazioni aritmetiche deve essere eseguita; le Variabili indicano quale sono le due colonne contenenti i numeri sui quali operare e in quale colonna deve essere posto il risultato. L'Analytical Engine dispone, continua Menabrea nella sua spiegazione, di uno speciale apparato chiamato fabbrica (mill), nel quale sono effettivamente eseguite le operazioni aritmetiche.

Per quel che riguarda le operazioni stesse, esse sono eseguite da uno speciale apparato, che è designato con il nome di fabbrica, e che contiene esso stesso un certo numero di colonne, simili a quelle delle variabili. Quando due numeri devono essere combinati insieme, la macchina [...] trasferisce i numeri nella fabbrica. Quindi, essendo stato l'apparato disposto in maniera opportuna per l'operazione richiesta, quest'ultima è eseguita e, quando completata, il risultato stesso è trasferito nella colonna delle Variabili che è stata indicata. Quindi la fabbrica è la porzione della macchina che lavora, e le colonne delle Variabili costituiscono il luogo dove i risultati sono rappresentati e immagazzinati.

La macchina, prosegue Menabrea, può assumere le necessarie disposizioni immagineimmagineper eseguire una serie di passi senza l'intervento dell'uomo utilizzando schede perforate, nella stessa maniera in cui le schede perforate sono usate nel telaio ideato da Jacquard. Nei tessuti si distinguono due tipi di fili: la trama e l'ordito. Attraverso l'opportuno intrecciarsi di questi fili è possibile realizzare disegni sui tessuti. Questo lavoro era eseguito a mano prima dell'invenzione del telaio meccanico di Jacquard, nel quale i fili sono collegati a leve il cui movimento è regolato attraverso l'uso di schede perforate: le leve che si trovano in corrispondenza con la parte solida della scheda sono obbligate a muoversi con la scheda stessa, mentre quelle che si trovano in corrispondenza con una delle perforazioni sono indipendenti dall'eventuale movimento della scheda. L'intreccio dei fili è quindi comandato dalle schede perforate; ad ogni azione del telaio una nuova scheda occupa il posto della precedente e comanda un diverso intreccio dei fili. Il risultato è la creazione di figure anche complesse sul tessuto. Menabrea ricorda che per alcuni disegni sono necessarie non meno di ventimila schede. In maniera analoga l'Analytical Engine può utilizzare le schede perforate. La macchina dispone di due tipi principali di schede:

in primo luogo, le schede delle Operazioni [Operation cards], per mezzo delle quali le parti della macchina sono disposte in modo da eseguire una determinata serie di operazioni, come addizioni, sottrazioni, moltiplicazioni e divisioni; secondariamente, le schede delle Variabili [cards of Variables], che indicano alla macchina le colonne nelle quali il risultato deve essere rappresentato.

In sintesi, le schede delle Operazioni indicano quali sono le operazioni che la macchina deve eseguire; le schede delle Variabili individuano le colonne sulle quali agire (ogni operazione richiede due colonne di dati sorgenti) e la colonna nella quale inserire il risultato.
Un terzo tipo di schede sarà successivamente indicato come necessario da Menabrea: le schede dei numeri (cards of numbers) che contengono le principali costanti matematiche

Questi sono determinati numeri, come quelli che esprimono il rapporto tra la circonferenza e il diametro, i Numeri di Bernoulli, ecc., che frequentemente si presentano nei calcoli. Per evitare la necessità di calcolarli ogni volta che devono essere utilizzati, certe schede possono essere combinate in maniera tale da fornire questi numeri pronti per l'uso [...].

Dopo aver spiegato i principi di funzionamento della macchina, Menabrea è pronto per illustrarli tramite un primo esempio: un programma che calcola la soluzione, rispetto alla variabile x, del sistema di due equazioni lineari

immagine

Tale soluzione è

immagine

Ecco come Menabrea descrive il programma per calcolare la soluzione indicata.

Continuiamo con il rappresentare mediante V0, V1, V2, ecc., le differenti colonne che contengono i numeri, e supponiamo che le prime otto colonne siano state scelte per esprimere i numeri rappresentati da m, n, d, m', n', d', n e n', il che implica che V0=m, V1=n, V2=d, V3=m', V4=n', V5=d', V6=n, V7=n'.

La serie delle operazioni comandate dalle schede, e i risultati ottenuti, possono essere rappresentati nella tabella seguente:

immagine

Cerchiamo di capire il significato della tabella presentata a Menabrea. Number of operations indica il numero successivo dei passi di esecuzione del programma. Operation-cards contiene le schede delle Operazioni, quelle che indicano quali sono le operazioni che la macchina eseguirà. Cards of the variables contiene le schede delle Variabili che individuano le varie colonne sulle quali la macchina agirà. Cards of variables è divisa in Columns on which operations are to performed, che riporta le colonne sorgenti, Column which receive results of operations, che riporta la colonna destinazione. Infine Progress of the operations riporta lo stato delle colonne contenenti i dati. In termini moderni la tabella nel suo complesso è la traccia passo-passo dell'esecuzione del programma. Da questa tabella è immediato risalire alle schede necessarie per scrivere effettivamente il programma. In prima approssimazione è richiesto un numero di schede pari al doppio dei passi; ogni passo individua infatti una scheda Operazioni e una scheda delle Variabili. In realtà il numero delle schede Operazioni può essere ridotto, come sottolinea Menabrea:

se richiesto, possiamo utilizzare solo tre schede operazioni; per realizzare ciò, è sufficiente introdurre nella macchina un apparato che consenta, per esempio, dopo la prima moltiplicazione, di trattenere la scheda relativa a questa operazione, e non le permetta di avanzare per essere rimpiazzata da un'altra, fino a quando questa operazione sia stata eseguita quattro volte.

Troviamo qui una prima descrizione della nozione di ciclo di un programma, cioè la possibilità di eseguire più volte una scheda o una serie di schede; questo concetto sarà ripreso in seguito sia da Menabrea sia da Ada Lovelace.
Subito dopo Menabrea presenta un secondo esempio di programma, consistente in una piccola variazione del primo programma, nel quale è calcolata anche la soluzione del precedente sistema di equazioni lineari rispetto alla variabile y. Non riporto la tabella di questo programma, poiché non aggiunge molto al programma iniziale. Nel commento a questo programma Menabrea nota che le colonne delle Variabili possono essere considerate un deposito (store) di numeri. Segue un ulteriore esempio, particolarmente semplice, avente lo scopo di mostrare che

La macchina non è soltanto capace di eseguire quei calcoli numerici che dipendono da una formula algebrica nota, ma è anche adatta per quei calcoli analitici [relativi cioè all'analisi matematica] nei quali devono essere considerate una o più variabili.

Anche in questo caso Menabrea presenta un programma di esempio, che ometto di descrivere perché estremamente semplice e privo di sostanziali novità. Risulta invece interessante la conclusione che ne trae Menabrea.

Possiamo dedurre la seguente importante conseguenza di questi esempi, e cioè che, poiché le schede indicano solo la natura delle operazioni che devono essere eseguite, e le colonne delle Variabili i dati sui quali eseguirle, queste schede posseggono loro stesse tutta la generalità dell'analisi, della quale esse sono in realtà una mera traduzione.

Immediatamente dopo questa affermazione, Menabrea spiega sinteticamente ma correttamente due concetti fondamentali della programmazione: la possibilità di eseguire due porzioni diverse di programma al verificarsi di un certo evento, e la possibilità di eseguire un ciclo di operazioni fino al verificarsi di una certa condizione. Si tratta di un punto molto importante. Nei tre programmi fino a questo punto presentati da Menabrea, tutte le istruzioni sono eseguite in successione, nell'ordine nel quale compaiono. Adesso Menabrea introduce altre due tecniche di programmazione: il test di una condizione per decidere quale porzione di schede eseguire, e il ciclo delle operazioni.
Relativamente al primo punto, Menabrea ne accenna in occasione dello studio delle funzioni che presentano punti di singolarità.

Ci sono certe funzioni che necessariamente cambiano di natura quando passano attraverso lo zero o l'infinito, o i cui valori non sono accettabili quando passano questi limiti. Quando questi casi si presentano, la macchina è capace, per mezzo di un campanello, di avvertire dell'avvenuto passaggio attraverso zero o infinito, e di fermarsi fino a quando l'operatore [attendant] la attiva nuovamente per qualsiasi processo sia desiderato che essa esegua. Se questo processo è stato previsto, allora la macchina, invece di suonare il campanello, si predisporrà per ricevere le nuove schede che hanno relazione con l'operazione che deve seguire il passaggio attraverso zero o infinito. Queste nuove schede possono seguire le prime, ma entrano in azione soltanto al verificarsi di una o l'altra delle due condizioni appena menzionate.

Se tratta di una descrizione, un poco pesante, del concetto di salto. Una serie di schede segue, dal punto di vista fisico, un'altra serie di schede, ma è eseguita solo al verificarsi di una certa condizione. Quando la macchina incontra un punto di singolarità smette di eseguire la prima serie di schede e passa ad eseguire la seconda serie di schede, letteralmente saltando in un'altra porzione di codice. Una piccola nota amena: già a quell'epoca era previsto il fastidiosissimo beep (o forse drin) al verificarsi di una condizione anomala. Segue un esempio dedicato al calcolo di un termine della forma abn, nel quale Menabrea utilizza esplicitamente un ciclo.

immagineConsideriamo un termine della forma abn; poiché le schede non sono altro che una traduzione della formula analitica [relativa all'analisi], il loro numero in questo caso particolare è sempre lo stesso, qualunque sia il valore di n [...] supponiamo per il momento che n sia un numero intero. Ora, poiché l'esponente n indica che b deve essere moltiplicato per se stesso n volte, è sufficiente impiegare una sola scheda-operazione, e cioè quella che ordina la moltiplicazione. Ma poiché n è dato per ogni caso particolare che deve essere calcolato, è richiesto l'ulteriore requisito che la macchina limiti il numero delle moltiplicazioni in accordo al valore dato. Il processo può essere così eseguito. I tre numeri a, b e n saranno scritti in tre distinte colonne del magazzino; le indichiamo come V0, V1, V2; il risultato abn finirà nella colonna V3. Quando il numero n sarà stato introdotto nella macchina, uno scheda ordinerà ad un certo apparato di registrazione [registering-apparatus] di segnare (n-1), e nello stesso tempo eseguirà la moltiplicazione di a per b. Quando questa sarà completata, si troverà che l'apparato di registrazione ha sottratto una unità, e segnerà soltanto (n-2); mentre la macchina ordinerà adesso di nuovo la moltiplicazione del numero b scritto nella colonna V1 per il numero b2 scritto nella colonna V3, che darà b3. Un'altra unità è adesso sottratta dall'apparato di registrazione, e lo stesso processo è continuamente ripetuto finché esso segna soltanto zero. Allora il numero bn sarà trovato in V3, quando la macchina, seguendo il corso delle operazioni, ordinerà il prodotto di bn per a; e il calcolo richiesto sarà stato completato senza che ci sia stata alcuna necessità di far variare il numero delle schede-operazione con il valore di n.

In questo esempio è esattamente descritto un ciclo con diminuzione della variabile di controllo ed uscita dal ciclo all'azzeramento della variabile. L'uso di questa tecnica consente, come bene indica Menabrea, di eseguire calcoli usando un numero fisso di schede, indipendentemente dal valore dei dati numerici pertinenti ad uno specifico problema.
L'articolo di Menabrea volge alla fine. Menabrea si chiede quale sarebbe l'utilità dell'Analytical Engine, ammesso che sia possibile costruirlo. L'autore individua tre punti:

  1. L'assoluta accuratezza.
  2. Il risparmio di tempo.
  3. Il risparmio di risorse intellettive.

Inoltre, sottolinea Menabrea, molte promettenti teorie, a causa della loro notevole complessità matematica, rischiano di restare al di fuori della scienza per la mancanza del potere sufficiente per calcolare i risultati numerici.

Quindi l'idea di costruire un apparato capace di aiutare la debolezza umana in queste ricerche, è una concezione che, se realizzata, segnerebbe un'epoca gloriosa nella storia della scienza.

Le note di Ada Lovelace.
Le note aggiunte da Ada Lovelace nella traduzione inglese dell'articolo di Menabrea sono identificate con le lettere dell'alfabeto, da A a G.

immagineLa nota A contiene una spiegazione delle sostanziali differenze tra il Difference Engine e l'Analytical Engine. L'aspetto che pare più interessante, in termini moderni, della nota A, è l'insistenza con la quale Ada Lovelace propone una scienza delle operazioni, cioè una teoria formale, facente parte della matematica, avente come proprio oggetto le operazioni stesse. Come fa notare Ada, esiste una intrinseca ambiguità nella notazione matematica, che non distingue tra l'operazione, il risultato dell'operazione e gli oggetti sui quali si opera. Posso fare un esempio per chiarire il pensiero di Ada. La scrittura 26 confonde tre diversi usi della notazione matematica: le cifre 2 e 6 indicano i numeri due e sei, ma anche l'operazione di elevazione a potenza e il risultato di tale operazione. Questo tipo di ambiguità deve essere risolto per la programmazione dell'Analytical Engine, nel quale è essenziale distinguere tra le operazioni, rappresentate dalle schede delle Operazioni, che indicano quali attività intraprendere, e i dati sui quali tali attività agiscono, rappresentati dalle schede delle Variabili. L'Analytical Engine, spiega Ada Lovelace, non agisce sui numeri, bensì esegue delle operazioni astratte ed indipendenti dal materiale numerico sottostante, al punto che l'Analytical Engine

può agire su altre cose oltre ai numeri, se le relazioni fondamentali degli oggetti possono essere espresse tramite quelle della scienza astratta delle operazioni [...] Se si suppone, per esempio, che le relazioni fondamentali dei suoni della scienza dell'armonia siano suscettibili di tale espressione e adattamenti, la macchina potrebbe comporre brani musicali elaborati e scientifici di ogni grado di complessità ed estensione.

Ciò che vuol dire Ada Lovelace è molto semplice e profondo: l'Analytical Engine non è una macchina che esegue solo calcoli numerici, ma può eseguire qualunque tipo di operazioni, anche non numeriche. Per questo non è limitata ai soli calcoli, ma ha lo stesso potere dell'algebra e dell'analisi astratta, e quindi può legittimamente trattare di tutte quelle materie riconducibili all'algebra e all'analisi. L'esempio proposto da Ada, relativo alla possibilità che l'Analytical Engine componga musica se questa è riconducibile a schemi di operazioni, serve a colpire il lettore e a fargli comprendere che le possibilità dell'Analytical Engine hanno la stessa estensione della scienza astratta delle operazioni (in termini moderni, la macchina esegue algoritmi e non calcoli numerici). Per questo, prosegue Ada, l'Analytical Engine potrebbe essere utilmente utilizzato per studiare problemi concernenti i numeri immaginari, intrattabili da qualsiasi macchina calcolatrice. Inoltre, sempre secondo Ada, dovrebbe essere facile per l'Analytical Engine aggiungere ai risultati numerici anche dei risultati simbolici,

i quali risultati simbolici sono la necessaria e logica conseguenza delle operazioni eseguite su dati simbolici, così come lo sono i risultati numerici quando i dati sono numerici.

Non si possono non ammirare gli sforzi che Ada Lovelace compie per tracciare una distinzione netta e precisa tra l'esecuzione di un calcolo e il calcolo in se stesso. Si tratta tra l'altro di una distinzione resa difficile dalla notazione matematica che si presta ad aumentare la confusione. Continua Ada Lovelace:

La caratteristica distintiva dell'Analytical Engine, e quella che ha reso possibile sviluppare un meccanismo con così estese possibilità da rendere questa macchina la mano destra esecutiva [nel testo originale "executive", nel senso di puramente operativo, che esegue le istruzioni] dell'algebra astratta, è l'introduzione in esso del principio che Jacquard ha ideato per regolare, mediante schede perforate, i più complicati schemi nella fabbricazione dei broccati. E' in questo che risiede la distinzione tra le due macchine [tra il Difference e l'Analytical Engine]. Niente del genere esiste nel Difference Engine. Noi possiamo dire, in maniera appropriata, che l'Analytical Engine tesse schemi algebrici così come il telaio di Jacquard stesse fiori e foglie.

In questo senso l'Analytical Engine ha superato i limiti dell'aritmetica e non ha nulla in comune con le macchine calcolatrici. Per questo, precisa Ada Lovelace, l'Analytical Engine non è il successore del Difference Engine, né il suo progetto può essere considerato in qualche modo correlato o suggerito da quello del Difference Engine. Si tratta di due macchine completamenti differenti, basati su principi intermante diversi. Il Difference Engine è una macchina calcolatrice perfezionata, il cui unico scopo è tabulare un particolare tipo di funzione matematica. Al contrario l'Analytical Engine esegue calcoli astratti, non limitati all'aritmetica, ed è basato su una teoria astratta delle operazioni.

La nota B tratta del metodo utilizzato per la memorizzazione dei dati numerici. Come già spiegato da Menabrea, i numeri sono memorizzati in colonne di dischi che rappresentato le unità, le decine, le centinaia, e così via. Il modo di memorizzazione dei numeri nell'Analytical Engine non differisce in maniera sostanziale da quello utilizzato nel Difference Engine. Il numero di cifre memorizzabili dipende dal numero di dischi che costituiscono una colonna. Nel progetto dell'Analytical Engine Babbage prevedeva la possibilità di utilizzare 20 dischi, per memorizzare numeri fino a 20 cifre. Un ulteriore disco è utilizzato per registrare il segno del numero.
La citazione seguente, tratta dalla nota B, mostra uno schema di notazione suggerito da Ada Lovelace. Nelle colonne V1, V2 e V3 sono memorizzati i numeri positivi 5, 7 e 98. La colonna è V4 vuota e contiene ancora il valore iniziale 0. Sotto le colonne vi è un quadrato che contiene

qualsiasi simbolo generale o combinazione di simboli che ci piace; si intende che il numero rappresentato nella colonna immediatamente sopra è il valore numerico di quel simbolo o combinazione di simboli. Per esempio, rappresentiamo le tre quantità a, n, x, e supponiamo inoltre che sia a=5, n=7, x=98. Avremo dunque:

immagine

E' importante notare che nella notazione suggerita da Ada Lovelace, il quadrato posto alla fine della colonna ha la funzione di un commento. immagineCi ricorda cioè quale variabile è rappresentata nella colonna in questione, ma non ha alcuna funzione nella macchina stessa, né ha alcun elemento fisico corrispondente. I nomi assegnati alle colonne (V1, V2, ecc.) hanno sia una funzione mnemonica sia la funzione di individuare la colonna fisica: la variabile Vn identifica infatti la n-esima colonna (in un certo senso di tratta di un meccanismo simbolico per indirizzare in modo assoluto le locazioni di memoria). Nel caso del segno, Ada propone una rappresentazione simbolica, ma la macchina in realtà registra un numero pari per il segno positivo, dispari per il segno negativo (questo è un esempio nel quale ad un valore numerico è associato un significato non numerico). Usando questa notazione, Ada mostra come si potrebbe rappresentare lo stato della macchina prima che essa calcoli l'espressione axn, dopo che le costanti numeriche sono state inserite nelle colonne opportune:


immagine

Trattando delle schede perforate usate per programmare l'Analytical Engine, Ada svolge le seguenti osservazioni.

Le schede delle Operazioni determinano soltanto la successione delle operazioni in un modo generale. Esse infatti pongono l'intera porzione del meccanismo incluso nella fabbrica in una serie di stati differenti, che noi possiamo chiamare lo stato dell'addizione, o lo stato della moltiplicazione, ecc., rispettivamente. In ciascuno di questi stati il meccanismo è pronto per agire nella maniera peculiare a quello stato, su ogni coppia di numeri che si permette di entrare nella sua sfera di azione. Solo uno di questi stati operativi della fabbrica può esistere in un certo istante [...].

Troviamo qui una descrizione molto precisa del funzionamento della fabbrica, che sempre più possiamo identificare con l'unità logico-aritmetica di un moderno calcolatore. La fabbrica passa attraverso una serie di stati, ciascuno dei quali è caratterizzato in maniera univoca dall'operazione che sarà eseguita; in ogni istante la macchina si trova in uno e in un solo uno di questi stati. Le schede delle Operazioni programmano la macchina in modo da attraversare una serie definita di stati. L'analogia con la macchina di Turing appare evidente (è utile ricordare che la nozione di macchina di Turing sarà introdotta circa novanta anni dopo la pubblicazione di questo articolo). La breve nota C spiega che, a differenza del telaio di Jacquard, in cui il nastro di schede può solo avanzare, nell'Analytical Engine è stato introdotto un meccanismo che consente al nastro di schede di retrocedere, in modo da poter eseguire più volte una o più schede.

Il modo di applicazione delle schede, come usato nell'arte della tessitura, fu comunque trovato non essere sufficientemente potente per tutte le semplificazioni che era desiderabile ottenere in così vari e complicati processi come quelli richiesti in ordine di realizzare gli scopi di un Analytical Engine. Fu escogitato un metodo tecnicamente designato backing per far retrocedere le schede in determinati gruppi in accordo a determinate leggi. L'oggetto di questa estensione è di assicurare la possibilità di utilizzare ogni particolare scheda o insieme di schede un qualsiasi numero di volte successivamente nella soluzione di un particolare problema. Il fare o non fare uso di questa possibilità, in ogni caso particolare, dipenderà dalla natura delle operazioni che il problema sotto esame può richiedere.

In questa descrizione della nozione di ciclo, è importante sottolineare la prima frase, secondo la quale l'esecuzione delle istruzioni in modo puramente sequenziale non è sufficientemente potente per gli scopi dell'Analytical Engine. Si tratta di una considerazione del tutto corretta, perché esistono algoritmi non esprimibili mediante una successione lineare di istruzioni. L'uso dei cicli è ripreso nella successiva nota F.

La nota D contiene alcune precisazioni sulla notazione utilizzata per rappresentare i programmi. In primo luogo

In tutti i calcoli, le colonne delle Variabili usate possono essere divise in tre classi:
1°. Quelle nelle quali i dati sono registrati [variabili per i dati: Variables for Data].
2°. Quelle destinate a ricevere i risultati finali [variabili per i risultati: Variables for Results].
3°. Quelle destinate a ricevere quelle combinazioni intermedie e temporanee dei dati primitivi che non devono essere permanentemente mantenute, ma sono soltanto necessarie per lavorare, al fine di conseguire i risultati finali. Combinazioni di questo genere possono essere propriamente chiamati dati secondari. Essi sono in realtà passi successivi verso il risultato finale. Le colonne che li ricevono sono giustamente chiamate Variabili di lavoro [Working-Variable], poiché il loro ufficio è per sua natura puramente sussidiario ad altri scopi. Essi producono una classe intermedia e transiente di risultati, che unisco i dati originali con i risultati finali.

Riassumendo, Ada distingue tra:

Correttamente Ada sottolinea che talvolta le variabili per i risultati hanno una natura simile alle variabili di lavoro, poiché frequentemente le variabili per i risultati sono utilizzate per registrare i valori dei calcoli intermedi necessari per arrivare al risultato. Ada introduce inoltre un'aggiunta alla notazione utilizzata da Menabrea. Le variabili dispongono di due indici (esempio: 1V3).

Gli indici inferiori sono ovviamente soltanto indici di localizzazione [locality], e sono totalmente indipendenti dalle operazioni eseguite o dai risultati ottenuti, e il loro valore rimangono invariabili durante le esecuzioni dei calcoli. Gli indici superiori, comunque, sono di una differente natura. Il loro ufficio è di indicare ogni alterazione nel valore che una Variabile rappresenta; e naturalmente possono variare durante il progresso di un calcolo. Quando una Variabile ha solo zeri, essa è chiamata 0V; quando un valore appare in essa (sia che il valore sia posto lì arbitrariamente, o che appaia nel corso naturale di un calcolo), essa diventa 1V. Se questo valore cede il posto a un altro valore, la Variabile diventa 2V, e così via. Ogniqualvolta un valore è sostituito dallo zero, la Variabile diventa nuovamente 0V, anche se il momento prima fosse stato nV. Se assume ancora un nuovo valore, la Variabile diventa n+1V.

Quindi 0V3 indica la variabile associata alla colonna 3 non ancora inizializzata (contenente cioè solo zeri). Quando in questa colonna è inserito un numero, la variabile è scritta come 1V3. I vantaggi di questa scrittura, sostiene Ada Lovelace, sono molteplici. In particolare, un'espressione come m+1Vn = qVp + mVn è più chiara e consistente con le leggi dell'algebra della corrispondente espressione Vn = Vp + Vn che non fa uso degli indici superiori (quest'ultima è la notazione effettivamente utilizzate negli odierni linguaggi di programmazione).

La nota E contiene alcune considerazioni sulla complessità dei cicli che l'Analytical Engine è in grado di gestire. Parlando dello sviluppo di funzioni tramite serie di funzioni più semplici, Ada nota che i termini successivi di tale sviluppo seguono sempre la medesima regola e quindi possono essere calcolati dalla macchina mediante

un ciclo di un ciclo di un ciclo, ecc., di operazioni, una, due, tre, fino a n-1 volte, al fine di ottenere la n-esima funzione.

In una nota a piè di pagina, Ada spiega che

Un ciclo che include n altri cicli, successivamente contenuti uno dentro l'altro, è chiamato un ciclo di ordine n+1. Un ciclo può successivamente includere molti altri cicli, ed essere ancora del secondo ordine. Se una serie segue una certa legge per un certo numero di termini, e quindi un'altra legge per un altro numero di termini, ci sarà un ciclo di operazioni per ogni nuova legge; ma questi cicli non saranno contenuti uno dentro l'altro, ma semplicemente seguiranno uno dopo l'altro. Quindi il loro numero può essere infinito senza influenza l'ordine di un ciclo che include una ripetizione di una tale serie.

Ada prevede chiaramente in questo passo la possibilità di annidare di cicli di operazioni e di avere cicli che contengono al loro interno, in forma non annidata ma successiva, altri cicli. Si capisce da queste citazioni e dalla frequenza con la quale Ada parla dei cicli di operazioni che ella aveva ben compreso l'importanza nella programmazioni di struttura cicliche annidate, che ben si prestano a risolvere problemi ricorrenti.
La maggior parte della nota E è dedicata allo sviluppo di alcuni esempi di calcolo relativi a funzioni trigonometriche; ometto la descrizione di questi esempi, a causa sia della loro complessità matematica, sia perché Ada non li sviluppa in maniera dettagliata. Vedremo tra poco, trattando la nota G, un esempio altrettanto complesso ma sviluppato da Ada in gran dettaglio, al punto che possiamo ricavarne un programma completo.

immagine

Nella nota F Ada mostra come l'uso dei cicli può ridurre in maniera drastica il numero di schede necessarie per risolvere un problema. L'esempio proposto consiste nel risolvere, mediante eliminazione delle variabili, un sistema di dieci equazioni lineari. Secondo Ada sarebbero necessarie 330 schede; con l'utilizzo dei cicli queste 330 schede si riducono a tre. Ancora più importante è la considerazione che questo ciclo di tre schede può essere usato per un qualsiasi sistema di n equazioni lineari, indipendentemente dal numero n.

La nota G contiene un esempio di programmazione piuttosto complesso: il calcolo dei numeri di Bernoulli. I numeri di Bernoulli Bn prendono il nome dal matematico Jacob Bernoulli e sono stati definiti dalla formula seguente (attualmente si utilizza una definizione diversa)

immagine

Talvolta si incontra anche questa formula:

immagine

Ada Lovelace utilizza la seguente formula per la definizione dei numeri di Bernoulli:

immagine

Attraverso alcuni passi matematici che ometto Ada arriva alla seguente formula equivalente che, nella numerazione della nota G, ha il numero (8):

immagine

I primi dieci numeri di Bernoulli sono riportati nella seguente tabella tratta da http://www.sosmath.com/tables/bernoulli/bernoulli.html.

immagine

Così Ada commenta la formula (8):

Ad un'attenta considerazione, ci accorgiamo che noi possiamo derivare da essa i valori numerici di tutti i Numeri di Bernoulli in successione, a partire proprio dal primo, ad infinitum, mediante le seguenti serie di calcoli:
1a Serie. - Sia n=1, e si calcoli (8) per questo valore di n. Il risultato è B1.
2a Serie. - Sia n=2. Si calcoli (8) per questo valore di n, sostituendo il valore di B1 appena ottenuto. Il risultato è B3.
3a Serie. - Sia n=3. Si calcoli (8) per questo valore di n, sostituendo i valori di B1, B3 prima ottenuti. Il risultato è B5. E così via, per ogni valore.

A questo punto Ada riporta una tabella che illustra lo stato delle macchina durante il calcolo di B7 (n=4). Per visualizzare questa tabella nella sua interezza, fare clic qui (la tabella è estratta da http://www.fourmilab.ch/babbage/sketch.html). La tabella si presenta come traccia passo-passo di un programma che utilizza la formula (8) per il calcolo dei numeri di Bernoulli, quando n=4, e quindi il prossimo numero di Bernoulli da calcolare è B7.
La prima parte della tabella proposta da Ada Lovelace è visualizzata nella successiva Tavola 1. La tabella completa continua in basso, con i restanti passi del programma (in totale sono presenti 25 righe), e a destra, dove sono riportate le 24 colonne dati (fare clic qui per visualizzare la tabella intera). La numerazione delle tavole (Tavola1, Tavola2, ecc...) è mia e serve per facilitare il riferimento alle varie porzioni della tabella; essa è infatti troppo grande per essere visualizzata in una sola schermata, e quindi la mostrerò in porzioni limitate, ciascuna delle quali è pertinente ad una diversa sezione del programma per il calcolo dei numeri di Bernoulli.

immagine

Per capire il programma è immagineovviamente necessario conoscere i valori iniziali delle variabili dati; tali valori sono riportati nella porzione di tabella (Tavola 2) riportata qui accanto. Le tre variabili dati V1, V2 e V3 contengono inizialmente i numeri 1, 2 e n rispettivamente. Nell'esempio proposto da Ada Lovelace n vale 4; tuttavia il programma presentato da Ada risulta sufficientemente generale da non essere influenzato dal valore corrente di n. Inizialmente n deve valere 1, come d'altronde spiegato da Ada nel commento alla formula (8), per il calcolo di B1.
Oltre a commentare la tabella proposta da Ada, in questo articolo sarà fornita una versione moderna del programma stesso, scritto in Java. Di fatto, la porzione di tabella presentata nella Tavola 2 sta per i seguenti passi:

V[1] = 1;
V[2] = 2;
V[3] = n;

E' opportuno notare che in un moderno linguaggio di programmazione è obbligatorio definire il tipo di dato rappresentato nelle variabili; in questo caso l'array V sarà definito di tipo double. Niente di ciò è presente nelle tabelle proposte da Ada e da Menabrea; in realtà nei loro esempi le variabili sono più simili alle locazioni di memoria utilizzate nei primi programmi in Assembler, senza alcun tipo specifico associato.
Torniamo alla Tavola 1 per ricavare la seguente porzione di codice:

V[4] = V[2] * V[3];
V[5] = V[2] * V[3];
V[6] = V[2] * V[3];
V[4] = V[4] - V[1];
V[5] = V[5] + V[1];
V[11] = V[4] / V[5];
V[11] = V[11] / V[2];
V[13] = V[13] - V[11];
V[10] = V[3] - V[1];

Ciascuna delle nuove variabili deve disporre di un'opportuna definizione e inizializzazione. Per esempio nella riga 6 della Tavola 1, nell'istruzione V[13] = V[13] - V[11] la variabile V[13] deve essere stata inizializzata a zero, come si deduce dal valore dell'indice soprascritto. Dal commento di Ada a questa istruzione, risulta che essa serve a cambiare il segno di V[11]; in linguaggio di programmazione contemporaneo, è più semplice scrivere V[13] = - V[11].
In definitiva, le istruzioni corrispondenti alla prime sei righe della Tavola1 calcolano il valore di

immagine

primo termine dello sviluppo di (8). A cosa serve la riga 7? Lo spiega Ada:

L'Operazione 7 sarebbe incomprensibile, se non si ricordasse che se noi eseguissimo il calcolo per n=1 invece che per n=4, l'Operazione 6 avrebbe completato il calcolo di B1 stesso, nel qual caso la macchina invece di continuare il proprio processo, dovrebbe porre B1 in V21; e quindi si sarebbe fermata o avrebbe iniziato le Operazioni 1, 2 ... 7 di nuovo per il valore di n(=2), al fine di iniziare il calcolo di B3; (avendo comunque avuto cura, prima di ricominciare, di rendere il numero in V3 uguale a due, aggiungendo una unità al precedente n=1 in quella colonna). Dunque l'Operazione 7 deve restituire un risultato uguale a zero (se n=1); o un risultato maggiore di zero, come nel caso presente [ricordo che Ada presenta il caso n=4]; e la macchina segue l'una o l'altra di queste due strade appena spiegate, a secondo dell'uno o dell'altro risultato dell'Operazione 7.

Quindi, dopo avere eseguito l'istruzione V[10] = V[3] - V[1] si deve eseguire un test per verificare se V[10] è uguale a zero; in caso affermativo in V[13] troviamo il valore di B1 e tale valore è inserito in una variabile opportuna (V[21]), dopodiché si aggiunge 1 a V[3] e il controllo torna alla riga 1; se invece V[10] è maggiore di zero il programma prosegue con la successiva riga 8. Si noti la mancanza di una qualsiasi simbologia per l'istruzione di salto condizionato; nell'esempio presentato da Ada non esiste alcun modo per indicare un test su una variabile, né per indicare un salto a fronte di una condizione, né per indicare a quale istruzione cedere il controllo. Non disponendo di queste possibilità, Ada deve utilizzare una descrizione verbale per indicare un semplice test per zero, il cui significato è comunque sufficientemente chiaro.
Quindi possiamo ottenere la seguente porzione di codice:

V[4] = V[2] * V[3];
V[5] = V[2] * V[3];
V[6] = V[2] * V[3];
V[4] = V[4] - V[1];
V[5] = V[5] + V[1];
V[11] = V[4] / V[5];
V[11] = V[11] / V[2];
V[13] = - V[11];
V[10] = V[3] - V[1];
if (V[10] == 0)
{ V[21] = V[13];
  V[3] = V[3] + 1;
  return;
}

Questo frammento di codice fornisce il primo numero di Bernoulli. Ho provato ad eseguirlo (dopo averlo completato con le necessarie definizione delle variabili e delle classi come richiesto dallo specifico linguaggio di programmazione usato) ed ho ottenuto il risultato B1 = - 1.5, in disaccordo con il valore corretto B1 = 0.166667. Infatti la riga 4 della Tavola 1 è errata: l'istruzione corretta è V[11] = V[4] / V[5] mentre nella tabella è indicato V[11] = V[5] / V[4].
Ciò è ovvio dal commento associato alla riga 4. Ada ha calcolato l'inverso del valore che voleva effettivamente ottenere. Correggendo la svista, si ottiene un programma che fornisce per B1 il valore corretto (come modulo) -0.1666667; e il segno? Ada dice esplicitamente:

Nella tabella e nel diagramma precedenti noi non consideriamo il segno di nessuno dei B, ma solo il loro valore numerico. La macchina naturalmente troverà il segno corretto per ciascuno di essi, ma noi non entreremo in alcun dettaglio addizionale di questo tipo di calcolo, come invece avremmo voluto fare.

Si può pensare che Ada Lovelace non abbia avuto a propria disposizione abbastanza spazio nelle note per trattare il problema del segno dei numeri di Bernoulli, ma ovviamente non è possibile ottenere un programma che generi i numeri corretti se non si tiene conto del segno; infatti, ignorando il segno, si andrebbe incontro ad errori anche nel valore numerico dei numeri di Bernoulli. Per questo nella nostra versione, pur cercando di restare fedeli alla tabella di Ada, dobbiamo obbligatoriamente trattare esplicitamente il segno. Ciò porta a sostituire l'istruzione
   V[21] = V[13];
con
   V[21] = Math.abs(V[13]);

Adesso si ottiene il risultato corretto per B1 = 0.166667. La tabella proposta da Ada continua con le successive istruzioni; ci interessa al momento questo frammento:

immagine

Così Ada commenta queste istruzioni:

Le schede 8, 9, 10 generano

immagine

[...] La scheda 12 esegue lo stesso ufficio che la scheda 7 faceva nella sezione precedente: quindi, se n fosse stato 2, l'undicesima operazione avrebbe completato il calcolo di B3.

Possiamo aggiungere le istruzioni corrispondenti alle schede 8 - 12 nella precedente porzione di programma; otteniamo dunque:

V[4] = V[2] * V[3];
V[5] = V[2] * V[3];
V[6] = V[2] * V[3];
V[4] = V[4] - V[1];
V[5] = V[5] + V[1];
V[11] = V[4] / V[5];
V[11] = V[11] / V[2];
V[13] = - V[11];
V[10] = V[3] - V[1];
if (V[10] == 0)
{ V[21] = Math.abs(V[13]);
  V[3] = V[3] + 1;
  return;
}
V[7] = V[2];
V[11] = V[6] / V[7];
V[12] = V[21] * V[11];
V[13] = V[12] + V[13];
V[10] = V[10] - V[1];
if (V[10] == 0)
{ V[22] = Math.abs(V[13]);
  V[3] = V[3] + 1;
  return;
}

Eseguendo il programma finora ottenuto si calcolano i primi due numeri di Bernoulli:

B1 = 0.166667
B2 = 0.033333

Si noti che nella formula proposta da Ada i numeri di Bernoulli hanno sempre indice dispari, e quindi il numero B3 della formula (8) corrisponde al numero B2 della tabella che elenca i numeri di Bernoulli; ma questa è una differenza che non crea alcun problema.
E' necessario un ulteriore commento al programma proposto da Ada: questo programma viene attivato più volte con i valori successivi di n = 1,2,3,4,5,..., in modo che ogni volta sia calcolato il successivo numero di Bernoulli Bn. Questo numero è memorizzato in una memoria opportuna (V21, V22, V23,...) dove rimane disponibile per le successive elaborazioni. Quando il programma viene per esempio attivato con n=5, le colonne V21 V22 V23 V24 contengono già i valori corretti per B1 B2 B3 B4.
Ed ecco la successiva porzione della tabella di Ada:

immagine

Le istruzioni corrispondenti alle schede 13-22 eseguono il calcolo di B5. L'istruzione corrispondente alla scheda 23 esegue il medesimo compito di quelle corrispondenti alle schede 7 e 11 precedenti. Le istruzioni previste dalle schede 13-22 sono le seguenti:

int i = 0;
do
{ V[6] = V[6] - V[1];
  V[7] = V[7] + V[1];
  V[8] = V[6] / V[7];
  V[11] = V[8] * V[11];
  V[6] = V[6] - V[1];
  V[7] = V[1] + V[7];
  V[9] = V[6] / V[7];
  V[11] = V[9] * V[11];
  V[12] = V[22+i] * V[11];
  V[12] = V[12] * Math.pow(-1,i-1);
  V[13] = V[12] + V[13];
  V[10] = V[10] - V[1];
  if (V[10] == 0)
  { V[20+n] = Math.abs(V[13]);
    V[3] = V[3] + 1;
    return;
  }
  i++;
} while (V[10] > 0);

E' necessario un commento a questa porzione di programma. Alcune istruzioni non sono presenti nella tabella di Ada. In particolare Ada non fornisce alcuna indicazione su come il programma individua la colonna nella quale memorizzare i successivi numeri di Bernoulli. Sappiamo dall'esempio proposto che B1 sarà memorizzato in V21, B2 in V22 e così via. Possiamo immediatamente comprendere che Bn è memorizzato in V20+n ma questa istruzione non è presentata da Ada. In realtà, dietro questa semplice istruzione è presente un concetto che sembra assente sia nell'articolo di Menabrea sia nelle note di Ada: la possibilità di individuare un colonna dati mediante un numero memorizzato in un'altra colonna dati. I numeri registrati nelle colonne dati sono pensati come valori numerici o anche come elementi simbolici (quando per esempio una cifra è usata per indicare il segno del numero presente nella colonna stessa), ma in nessun caso è presa in considerazione la possibilità che essi rappresentino un'altra colonna dati. In definitiva nei programmi proposti manca una istruzione fondamentale: l'indirizzamento della memoria mediante riferimento al valore numerico presente in un'altra locazione di memoria. Questa mancanza è di natura diversa dalle altra mancanze segnalate. E' vero che non è presentata alcuna scheda di Operazioni per il test di una condizione, il salto condizionato o il ciclo, ma in questi casi si sopperisce a tale mancanza attraverso una descrizione verbale ma precisa del comportamento che dovrebbe assumere la macchina. Questo fatto suggerisce che Menabrea e Ada avevano presenti alcuni tipi di istruzioni fondamentali come il test, il salto e il ciclo, ma mancavano della nozione di indirizzamento della memoria tramite una variabile dati. Per questo l'istruzione

V[20+n] = Math.abs(V[13]);

deve essere considerate come una istruzione contemporanea, che non trova giustificazione negli esempi proposti da Ada e Menabrea, ma senza la quale il programma per il calcolo dei numeri di Bernoulli non potrebbe funzionare. Un'altra istruzione differente rispetto a quelle previste da Ada è

V[12] = V[22+i] * V[11];

Anche in essa è presente un indirizzamento di memoria mediante l'utilizzo di un'altra variabile (in questo caso la variabile i) che non è presente nel programma di Ada; proprio per sottolineare tale assenza, ho scelto di chiamare tali variabili i o n, differenziandole anche nella notazione dalle variabili V previste da Ada. Devo però citare il seguente passo presente sempre nella nota G.

[...] l'Operazione 21 richiede sempre uno dei suoi fattori da una nuova colonna, e l'Operazione 24 mette sempre il proprio risultato in una nuova colonna. Ma poiché queste variazioni seguono la medesima legge ad ogni ripetizione (l'Operazione 21 richiedendo sempre il suo fattore da una colonna che precede immediatamente quella usata la volta precedente, e l'Operazione 24 ponendo sempre il proprio risultato nella colonna che precede immediatamente quella che aveva ricevuto il precedente risultato), esse [le variazioni di colonna] possono essere facilmente realizzate nella disposizione del gruppo ricorrente (o ciclo) delle schede delle Variabili.

In questo passo Ada cerca di determinare come individuare la colonna variabile sulla quale agire, il che mostra che aveva presente il problema; la soluzione proposta mi sembra però legata alla particolare disposizione delle schede delle variabili in questo caso specifico e non generale (in termini tecnici, l'offset utilizzato per individuare la colonna dati è una costante=1 e non una variabile). La seguente istruzione

V[12] = V[12] * Math.pow(-1,i-1);

risolve il problema lasciato aperto da Ada e relativo al segno corretto dei numero di Bernoulli, agendo in maniera opportuna sul segno dei coefficiente previsti nella formula (8).
Le istruzioni precedenti sono racchiuse in un ciclo, da ripetersi fino a quando la variabile V10 non si annulla. Ciò è esplicitamente previsto da Ada:

Si comprenderà che ogni unità aggiunta a n in B2n-1 produce una ulteriore ripetizione delle operazioni (13...23) per il calcolo di B2n-1.

Inoltre anche la porzione successiva (e conclusiva) della tabella (vedi la successiva Tavola 5) indica la necessità di una ripetizione delle operazioni da 13 a 23.

immagine

L'istruzione presente nella scheda 25 incrementa di una unità la variabile V3 (la variabile n); dopodiché il programma è pronto per calcolare il successivo numero di Bernoulli. Questa istruzione è mantenuta in un ciclo esterno nella mia realizzazione del programma proposto da Ada (fare clic qui per scaricare il sorgente).
In definitiva il programma presentato da Ada Lovelace è sostanzialmente corretto e, una volta completato con le istruzioni proprie di un determinato linguaggio di programmazione, consente effettivamente il calcolo dei numeri di Bernoulli. E' inoltre un programma abbastanza complesso, sia nella parte matematica sia nella programmazione. Le difficoltà che l'autore deve aver affrontato sono maggiori di quelle che possiamo percepire oggi, tenuto conto che questo programma è stato pubblicato nel 1843, in mancanza di una teoria dei computer e dei computer stessi.

Non si può concludere questo articolo senza prendere in considerazione una celebre affermazione di Ada Lovelace che apre la nota G.

E' desiderabile guardarsi contro la possibilità di idee esagerate che potrebbero sorgere circa le potenzialità dell'Analytical Engine. Nel considerare un qualsiasi nuovo soggetto, c'è frequentemente una tendenza, primo, di sopravvalutare ciò che noi troviamo essere già interessante o rimarchevole; e, secondariamente, per una sorta di naturale reazione, di sottovalutare il vero stato delle cose, quando noi scopriamo che le nostre aspettative hanno sorpassato ciò che era realmente sostenibile. L'Analytical Engine non ha alcuna pretesa di produrre alcunché. Può fare tutto quello che noi sappiamo come ordinargli di eseguire. [The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform.] Può seguire un'analisi; ma non ha alcuna capacità di anticipare alcuna relaziona analitica o verità.

Mi limito a citare questa affermazione di Ada Lovelace, senza tentare alcun commento. Credo invece sia molto interessante citare e commentare quello che Ada scrive alcune righe dopo.

[...] è probabile che eserciti una influenza indiretta e reciproca sulla scienza stessa in un'altra maniera. Infatti, nel modo di distribuire e combinare le verità e le formule dell'analisi affinché diventino più facilmente e rapidamente comprensibili alla macchina, le relazioni e la natura di molti soggetti in questa scienza sono necessariamente posti sotto una nuova luce, e più profondamente investigati.

In questo passo Ada mostra una profonda comprensione delle problematiche inerenti la programmazione dei calcolatori. Secondo Ada, la necessità di rendere comprensibili le formule dell'analisi ad una macchina, produrrà degli studi più profondi sulla natura di queste relazioni, al punto di influenzare la matematica stessa. In effetti la nascita e la diffusione dei calcolatori sono stati accompagnati dallo sviluppo di nuovi settori della matematica, quali la teoria della complessità degli algoritmi, la teoria delle macchine di Turing, la teoria delle funzioni ricorsive, il lambda-calcolo, la teoria dell'informazione e la cibernetica. I calcolatori, lungi dall'essere solo un mero strumento per eseguire rapidamente e con sicurezza calcoli ripetitivi, hanno generato la necessità di uno sviluppo di nuovi settori della matematica, alcuni dei quali, senza i calcolatori, avrebbero uno scarso interesse teorico e pratico. Ciò non significa che le citate discipline matematiche siano nate al servizio dei calcolatori: per esempio la teoria delle funzioni ricorsive, il lambda-calcolo e la teoria delle macchine di Turing esistevano prima dello sviluppo dei calcolatori elettronici, ma interessavano solo un ristretto numero di logici e filosofi. Grazie ai calcolatori, sono diventati patrimonio comune di informatici e matematici.


immagine

Note bibliografiche.
La traduzione inglese dell'articolo di Menabrea, con le note di Ada Lovelace, è reperibile in http://www.fourmilab.ch/babbage/sketch.html

Notizie biografiche su Menabrea e Ada Lovelace sono reperibili in:
http://www-history.mcs.st-andrews.ac.uk/history/Mathematicians/Menabrea.html
http://www-history.mcs.st-andrews.ac.uk/history/Mathematicians/Lovelace.html

Nel sito della scuola Dagomari del Comune di Prato è presente un museo virtuale del computer, con informazione e immagini sulla storia del computer, relative anche al telaio di Jacquard e a Charles Babbage:
http://www.scuole.prato.it/dagomari/museo/htm/ingresso.htm

I seguenti articoli pubblicati su Scientific American parlano di Babbage e Ada Lovelace:
Redeeming Charles Babbage's Mechanical Computer, di Doron D. Swade, febbraio 1993
Ada and the First Computer, di Eugene Eric Kim e Betty Alexandra Toole, maggio 1999

L'autobiografia di Babbage:
Charles Babbage, Passages from the Life of a Philosopher, a cura di Martin Campbell-Kelly, Pickering & Chatto Ltd, 1994