Perché scrivere prove matematiche è più a prova di errore che scrivere codice per computer?


190

Ho notato che trovo molto più facile scrivere prove matematiche senza fare errori, piuttosto che scrivere un programma per computer senza bug.

Sembra che questo sia qualcosa di più diffuso della mia esperienza. La maggior parte delle persone crea continuamente bug nel software durante la programmazione e ha il compilatore per dire sempre qual è l'errore. Non ho mai sentito parlare di qualcuno che ha scritto un grosso programma per computer senza errori in una sola volta, e ho avuto piena fiducia che sarebbe stato senza errori. (In effetti, quasi nessun programma è privo di errori, anche molti di quelli altamente debug).

Eppure le persone possono scrivere interi articoli o libri di prove matematiche senza che nessun compilatore abbia mai dato loro il feedback che hanno fatto un errore, e talvolta senza nemmeno ricevere feedback dagli altri.

Vorrei essere chiaro. questo non vuol dire che le persone non commettano errori nelle prove matematiche, ma anche per i matematici con poca esperienza, gli errori di solito non sono così problematici e possono essere risolti senza l'aiuto di un "oracolo esterno" come un compilatore che punta al tuo sbaglio.

In effetti, se così non fosse, allora la matematica non sarebbe quasi possibile, mi sembra.

Quindi questo mi ha portato a porre la domanda: cosa c'è di così diverso nello scrivere prove matematiche impeccabili e nello scrivere un codice informatico impeccabile che lo rende così il primo è molto più tracciabile del secondo?

Si potrebbe dire che è semplicemente il fatto che le persone hanno l '"oracolo esterno" di un compilatore che li indica i loro errori che rende pigri i programmatori, impedendo loro di fare ciò che è necessario per scrivere rigorosamente il codice. Questa visione significherebbe che se non avessero un compilatore, sarebbero in grado di essere impeccabili come i matematici.

Potresti trovare questo convincente, ma in base alla mia esperienza di programmazione e scrittura di prove matematiche, mi sembra intuitivamente che questa non sia davvero una spiegazione. Sembra esserci qualcosa di sostanzialmente diverso nei due tentativi.

Il mio pensiero iniziale è che quella che potrebbe essere la differenza è che per un matematico, una prova corretta richiede solo che ogni singolo passo logico sia corretto. Se ogni passaggio è corretto, l'intera prova è corretta. D'altra parte, affinché un programma sia privo di errori, non solo ogni riga di codice deve essere corretta, ma deve funzionare anche la sua relazione con ogni altra riga di codice nel programma.

In altre parole, se il passaggio in una dimostrazione è corretto, allora commettere un errore nel passaggio non rovinerà mai il passaggioMa se una riga del codice è scritta correttamente, allora fare un errore nella riga influenzerà il funzionamento della riga , così che ogni volta che scriviamo la riga dobbiamo tener conto della sua relazione con tutte le altre righe. Possiamo usare l'incapsulamento e tutte queste cose per limitare questo, ma non può essere rimosso completamente.Y X X Y X XXYXXYXX

Ciò significa che la procedura per il controllo degli errori in una prova matematica è essenzialmente lineare nel numero di passaggi di prova, ma la procedura per il controllo degli errori nel codice del computer è essenzialmente esponenziale nel numero di righe di codice.

Cosa ne pensi?

Nota: questa domanda ha un gran numero di risposte che esplorano una grande varietà di fatti e punti di vista. Prima di rispondere, leggi tutti e rispondi solo se hai qualcosa di nuovo da aggiungere. Le risposte ridondanti o le risposte che non supportano le opinioni con fatti possono essere eliminate.


3
Sei a conoscenza di prove di correttezza per programmi, sia su supporto cartaceo che meccanizzato nei dimostratori di teoremi? Entrambi esistono e contraddicono il tuo aggiornamento. è vero che la programmazione come comunemente insegnata ha poco a che fare con la programmazione con prove di correttezza.
Blaisorblade,

76
Mi ricorda una citazione di Knuth, penso "Attenzione al codice sopra! Ho solo dimostrato che è corretto, non l'ho mai provato"
Hagen von Eitzen,

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Gilles,

7
Trovami una prova matematica scritta a mano che sia lunga 100 milioni di righe e non abbia "bug", e ti darò tutto ciò che possiedo.
Davor

I programmi funzionali possono essere molto più facili da scrivere delle prove, tuttavia, non appena arriva lo stato ... la difficoltà esplode ...
aoeu256,

Risposte:


226

Lasciami offrire una ragione e un malinteso come risposta alla tua domanda.

Il motivo principale per cui è più facile scrivere (apparentemente) prove matematiche corrette è che sono scritte a un livello molto alto. Supponiamo che tu possa scrivere un programma come questo:

function MaximumWindow(A, n, w):
    using a sliding window, calculate (in O(n)) the sums of all length-w windows
    return the maximum sum (be smart and use only O(1) memory)

Sarebbe molto più difficile sbagliare durante la programmazione in questo modo, poiché le specifiche del programma sono molto più sintetiche della sua implementazione . In effetti, ogni programmatore che cerca di convertire lo pseudocodice in codice, specialmente in codice efficiente, incontra questo grande abisso tra l' idea di un algoritmo e i suoi dettagli di implementazione . Le prove matematiche si concentrano maggiormente sulle idee e meno sui dettagli.

La vera controparte del codice per le prove matematiche sono le prove computerizzate . Questi sono molto più difficili da sviluppare rispetto alle solite prove testuali, e spesso si scoprono vari angoli nascosti che sono "ovvi" per il lettore (che di solito non li nota nemmeno), ma non così ovvi per il computer. Inoltre, poiché al momento il computer può riempire solo lacune relativamente piccole, le prove devono essere elaborate a un livello tale che un uomo che le legge mancherà la foresta per gli alberi.

Un malinteso importante è che le prove matematiche sono spesso corrette. In realtà, questo è probabilmente piuttosto ottimista. È molto difficile scrivere prove complicate senza errori e spesso i documenti contengono errori. Forse i casi più celebri recenti sono il primo tentativo di Wiles di (un caso speciale di) teorema di modularità (che implica l'ultimo teorema di Fermat), e varie lacune nella classificazione di gruppi semplici finiti, tra cui circa 1000+ pagine su gruppi quasithin che erano scritto 20 anni dopo la presunta conclusione della classificazione.

Un errore in un articolo di Voevodsky gli ha fatto dubitare così tanto delle prove scritte che ha iniziato a sviluppare la teoria del tipo di omotopia , un quadro logico utile per sviluppare formalmente la teoria dell'omotopia, e d'ora in poi ha usato un computer per verificare tutto il suo lavoro successivo (almeno secondo il suo ammissione). Sebbene questa sia una posizione estrema (e attualmente poco pratica), è sempre vero che quando si utilizza un risultato, si dovrebbe andare oltre la prova e verificare se è corretta. Nella mia zona ci sono alcuni documenti che sono noti per essere sbagliati ma che non sono mai stati ritirati, il cui status viene trasmesso dalla bocca agli orecchi tra gli esperti.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
DW

1
È possibile che in futuro vengano utilizzati gli assistenti di prova per controllare sia il codice che la prova? Forse è tempo di imparare te un Agda ? (scusa ...)
Alex Vong,

3
@AlexVong Un problema è che scrivere una specifica formale per un codice non banale (in modo da poter verificare che il codice soddisfi effettivamente la specifica) è quasi impossibile. Ad esempio, puoi immaginare quanto complicata sarebbe una specifica formale per un browser (comprese tutte le interazioni dell'utente, tutti i formati di file e protocolli supportati, ecc.)?
svick,

2
@svick Hai ragione, per l'interazione dell'utente, a volte non è nemmeno chiaro quale dovrebbe essere il comportamento giusto. Quindi dovremmo invece concentrarci su qualcosa con una specifica formale adeguata (ad esempio, prova, compilatore).
Alex Vong,

1
Infatti. Questa potrebbe anche essere una spiegazione del perché molte persone troverebbero la codifica in lingue di livello inferiore molto più noiosa e meno divertente della codifica in lingue astratte di alto livello. Sebbene ciò possa anche differire da persona a persona, ovviamente (alcuni potrebbero persino apprezzare la costruzione di circuiti hardware / elettronici di livello molto più basso rispetto alla scrittura di software in esecuzione su di essi? Inoltre, il codice di livello inferiore può ancora essere insostituibile in molti casi e scriverlo bene può essere una scarsa abilità / impresa degna di encomio da sola).
xji,

77

(Probabilmente sto rischiando alcuni voti bassi qui, poiché non ho tempo / interesse per rendere questa una risposta corretta, ma trovo che il testo citato (e il resto dell'articolo citato) sia abbastanza perspicace, anche considerando che sono scritti da un noto matematico. Forse potrei migliorare la risposta in seguito.)

L'idea, che suppongo non sia particolarmente distinta dalla risposta esistente, è che una "prova" o argomento comunica a una comunità matematica, dove lo scopo è di convincerli che i dettagli (noiosi) possono essere riempiti, in linea di principio, per ottenere una prova formale completamente specificata, senza farlo spesso. Un'istanza critica di ciò è che puoi usare i teoremi esistenti semplicemente dichiarandoli, ma il riutilizzo del codice è molto più impegnativo in generale. Considera anche "bug" minori, che possono rendere completamente inutile un pezzo di codice (ad esempio, SEGFAULTs) ma possono lasciare in gran parte intatto un argomento matematico (vale a dire, se l'errore può essere contenuto senza l'argomentazione dell'argomento).

Lo standard di correttezza e completezza necessario per far funzionare un programma per computer è un paio di ordini di grandezza superiori allo standard di prove valide della comunità matematica. Tuttavia, i programmi per computer di grandi dimensioni, anche quando sono stati scritti con molta attenzione e testati con molta attenzione, sembrano sempre avere dei bug. [...] La matematica, dal momento che la pratichiamo, è molto più completa formalmente e precisa rispetto ad altre scienze, ma è molto meno formalmente completa e precisa per il suo contenuto rispetto ai programmi per computer. La differenza non riguarda solo la quantità di sforzo: il tipo di sforzo è qualitativamente diverso. Nei programmi per computer di grandi dimensioni, è necessario dedicare un'enorme quantità di sforzi a una miriade di problemi di compatibilità: assicurarsi che tutte le definizioni siano coerenti, sviluppare "buone" strutture di dati che hanno una generalità utile ma non ingombrante, decidendo sulla "giusta" generalità per le funzioni, ecc. La percentuale di energia spesa nella parte operativa di un grande programma, distinta dalla parte contabile, è sorprendentemente piccola. A causa di problemi di compatibilità che quasi inevitabilmente sfuggono di mano perché le definizioni "giuste" cambiano man mano che vengono aggiunte generalità e funzionalità, i programmi per computer di solito devono essere riscritti frequentemente, spesso da zero.

SULLA PROVA E SUL PROGRESSO IN MATEMATICA (pagg. 9-10), di WILLIAM P. THURSTON https://arxiv.org/pdf/math/9404236.pdf


3
Il punto sul "riutilizzo del codice" è abbastanza a proposito. Tradurre una lunga prova dal russo all'inglese richiede parecchi tipi di digitazione ; ma tradurre un programma per computer di grandi dimensioni da, diciamo, C ++ in Java, richiede un bel po 'di pensiero . Inoltre, risuscitare una prova di 3000 anni in greco antico è altrettanto facile; resuscitare un programma di 30 anni in PL / 1 è altrettanto difficile o più difficile.
Quuxplusone,

2
Anche l'esempio del greco antico mi ha fatto capire: i programmatori di computer usano una tonnellata di slang e colloquiali locali, come (void*)1e open('/dev/null'), che potrebbe non essere portatile tra diverse sottoculture, per non parlare della traduzione nella lingua di destinazione. (Il lettore deve solo sgridare la loro semantica approssimativa a forza di una lunga esperienza.) Penso che le prove matematiche contengano meno di questo tipo di "gergo". Se una prova usa una parola, il suo significato universale attuale dovrebbe essere deducibile dal lettore in qualche modo. I programmi per computer non hanno nemmeno significati universali!
Quuxplusone,

1
00

@Nat puoi elaborare? Non capisco
Gregory Magarshak,


55

Consentitemi di iniziare citando EW Dijkstra:

"La programmazione è una delle branche più difficili della matematica applicata; è meglio che i matematici più poveri rimangano puri matematici." (da EWD498)

Sebbene ciò che Dijkstra intendesse con "programmazione" differisca un po 'dall'uso attuale, c'è ancora qualche merito in questa citazione. Le altre risposte hanno già menzionato che il livello di astrazione in matematica può essere molto più alto rispetto alla programmazione, il che significa che possiamo ignorare alcune parti difficili se lo desideriamo.

Tuttavia, credo che questa sia semplicemente una conseguenza di una differenza più fondamentale tra una prova e un programma per computer, che è il loro scopo .

Lo scopo principale di una dimostrazione matematica è, tra l'altro, convincersi che un'affermazione matematica è corretta e, forse ancora più importante, raggiungere la comprensione . Pertanto, puoi scegliere di lavorare solo nel mondo matematico, dove tutto è creato in modo tale che la comprensione possa essere raggiunta dal design (anche se alcuni studenti suppongono di differenziarsi ...) Questo è esattamente ciò che Dijkstra intendeva con "matematici puri", quelli che (quasi) si occupano solo di fatti matematici e di comprenderne le proprietà.

Quindi, non dovresti essere sorpreso nel produrre prove corrette che siano relativamente a prova di errore: è il punto dell'intero "esercizio". (Tuttavia, questo non significa che gli errori non esistano o esistano a malapena, errare è solo umano, dicono)

Ora, se consideriamo la programmazione, qual è il nostro scopo? Non cerchiamo davvero la comprensione, vogliamo qualcosa che funzioni . Ma quando qualcosa "funziona"? Qualcosa funziona quando abbiamo creato con successo qualcosa che consente a una strana macchina di completare l'attività che vogliamo che faccia e preferibilmente anche abbastanza velocemente.

Questa è, credo, la differenza fondamentale, poiché significa che il nostro obiettivo non può essere semplicemente definito come un teorema che il nostro programma "dimostra", desideriamo qualcosa nel mondo reale (qualunque cosa sia), non un manufatto matematico. Ciò significa che non possiamo puramente teoricamente raggiungere il nostro obiettivo (anche se Dijkstra vorrebbe farcelo provare in modo irregolare) in quanto dobbiamo placare la macchina, sperare che in realtà sappiamo quale compito vogliamo che faccia e anche essere consapevoli di cose che nessuno ha considerato, eppure accadono in qualche modo.

Quindi, alla fine, non c'è altro modo che provarlo e probabilmente fallire, riparare, fallire e riprovare fino a quando non siamo abbastanza soddisfatti del risultato.


Nota che la tua ipotesi di scrivere prove prive di errori è più semplice dei programmi privi di errori (che sono in realtà dichiarazioni diverse come sottolinea @Ariel ) potrebbe in realtà essere errata, poiché le prove sono spesso costruite tramite prove ed errori a un certo livello. Spero comunque che questo faccia luce sulla domanda che è implicita: "Qual è davvero la differenza tra dimostrare un teorema e scrivere un programma?" (A cui un osservatore distratto della corrispondenza Curry-Howard potrebbe dire: "Niente affatto!")


Come @wvxvw menzionato nei commenti, i seguenti paragrafi delle "note sulla programmazione strutturata" (EWD249, pagina 21) sono molto rilevanti:

(...) Un programma non è mai un obiettivo in sé; lo scopo di un programma è evocare i calcoli e lo scopo dei calcoli è stabilire l'effetto desiderato. Sebbene il programma sia il prodotto finale realizzato dal programmatore, i possibili calcoli evocati da esso - il "fare" di cui è lasciato alla macchina! - sono la vera materia del suo commercio. Ad esempio, ogni volta che un programmatore afferma che il suo programma è corretto, fa davvero un'affermazione sui calcoli che può evocare.

(...) In un certo senso la realizzazione di un programma è quindi più difficile della realizzazione di una teoria matematica: sia il programma che la teoria sono oggetti strutturati e senza tempo. Ma mentre la teoria matematica ha senso così com'è, il programma ha senso solo attraverso la sua esecuzione.


2
Sono solo un laico; a cosa si riferiva Dijkstra per "programmazione"?
Ovi,

2
@Ovi Non ne sono proprio sicuro, ma la differenza principale è che parla di problemi algoritmici (non banali) che risolvono più di compiti di programmazione "generali", cioè sicuramente non sta parlando di qualche programma CRUD che deve connettere alcuni architetture esistenti o altri componenti ecc. Ulteriori informazioni sull'opinione di Dijkstra sulla programmazione possono essere viste in questa risposta
Lucertola discreta

3
Valuta per la citazione di Dijkstra, ma hai scelto il posto sbagliato! Ha scritto molto su questo problema nei primi paragrafi di Programmazione strutturata. Non vorrei alterare la tua risposta inviando un preventivo diverso, ma spero che tu cerchi di aggiungere altro da quel documento alla tua risposta!
wvxvw,

@Ovi la mia ipotesi sulla tua domanda è che la programmazione ai tempi di Dijkstra significasse più spesso scrivere codice assembly rispetto all'era moderna dei linguaggi di alto livello. Allo stesso modo, sto leggendo l'edizione 1974 di Mythical Man-Month, i concetti sono ancora attuali, ma i riferimenti tecnici sono assemblatore a livello di sistema o PL / I, molto diverso da quello che la maggior parte della gente pensa di programmare oggi
JimLohse,

46

Lamport fornisce alcuni motivi per dissentire sulla prevalenza di errori nelle prove in Come scrivere una prova (pagine 8-9) :

Circa venti anni fa, ho deciso di scrivere una prova del teorema di Schroeder-Bernstein per una lezione di matematica introduttiva. La prova più semplice che ho trovato è stata nel classico testo di topologia generale di Kelley. Dato che Kelley stava scrivendo per un pubblico più sofisticato, ho dovuto aggiungere molte spiegazioni alla sua dimostrazione di mezza pagina. Avevo scritto cinque pagine quando mi resi conto che la prova di Kelley era sbagliata. Di recente, ho voluto illustrare una lezione sul mio stile di prova con una convincente prova errata, quindi mi sono rivolto a Kelley. Non ho trovato nulla di sbagliato nelle sue prove; sembrava ovviamente corretto! Leggere e rileggere la prova mi ha convinto che o la mia memoria era fallita, oppure ero molto stupido venti anni fa. Tuttavia, la prova di Kelley era breve e sarebbe stata un buon esempio, quindi ho iniziato a riscriverla come prova strutturata.

... Lo stile è stato applicato per la prima volta alle prove dei teoremi ordinari in un documento che ho scritto con Martin Abadi. Aveva già scritto prove convenzionali, prove sufficienti per convincere noi e, presumibilmente, gli arbitri. Riscrivendo le prove in uno stile strutturato, abbiamo scoperto che quasi tutti avevano errori gravi, sebbene i teoremi fossero corretti. Qualsiasi speranza che prove errate non possano portare a teoremi errati è stata distrutta nella nostra prossima collaborazione. Di volta in volta, facevamo una congettura e scrivevamo uno schizzo di prova sulla lavagna - uno schizzo che avrebbe potuto facilmente trasformarsi in una prova convenzionale convincente - solo per scoprire, provando a scrivere una prova strutturata, che la congettura era falsa. Da allora, non ho mai creduto ad un risultato senza una prova attenta e strutturata.


6
Stesso documento: "Le prove aneddotiche suggeriscono che almeno un terzo di tutti gli articoli pubblicati su riviste matematiche contengono errori - non solo errori minori, ma teoremi e prove errati". Bene, era negli anni '90, ma oggi è diverso? Probabilmente quei documenti esistenti a quei tempi, esistono ancora e tutto si accumula ... Quindi, non sono del tutto convinto che le prove matematiche fornite nei documenti contengano meno errori.
MarkokraM,

Aneddoto affascinante, ma non vedo che risponda o si impegni direttamente con la domanda. Desideri modificare la tua risposta per rispondere più direttamente alla domanda che è stata posta? Stai sostenendo che le prove matematiche sono altrettanto difettose della scrittura del codice del computer? Hai ulteriori prove di ciò che puoi fornire? Un aneddoto o due non lo dimostrano davvero, vero?
DW

@DW Mando un messaggio di posta elettronica a Leslie se, può fornire ulteriori prove per la richiesta.
MarkokraM,

3
@DW Leslie disse nella sua sincera risposta che il suo collega fece un'indagine con 51 prove pubblicate su Math Reviews a quel tempo. A suo avviso, è più che aneddotico, ma non adatto a prove concrete a causa di diversi fatti. Il caso è stato più complicato perché si sono verificati alcuni errori sulle prove perché utilizzavano prove di prove prive di errori precedentemente pubblicate, ecc. Sarebbe un ottimo argomento di ricerca ma richiede così tanto lavoro. Come verificare le prove matematiche a livello di codice è ancora una domanda enorme. Le app create per l'assistenza interattiva di prova sono in fase molto iniziale. Almeno l'interfaccia di loro.
MarkokraM,

@DW L'aneddoto o due dimostrano come una dimostrazione matematica possa apparire "corretta" ma in realtà non corretta. A chiunque abbia sia scritto un complesso algoritmo informatico sia fatto una dimostrazione matematica, provando a scrivere un algoritmo informatico come una dimostrazione matematica e scoprendo quindi come l'algoritmo di alto livello sia tradito da molti, molti bug nei dettagli, il risultato non è affatto sorprendente.
Yakk,

39

Una grande differenza è che i programmi sono tipicamente scritti per operare su input, mentre le prove matematiche generalmente iniziano da un insieme di assiomi e teoremi noti in precedenza. A volte è necessario coprire più casi angolari per ottenere una prova sufficientemente generale, ma i casi e la loro risoluzione sono esplicitamente elencati e l'ambito del risultato è implicitamente limitato ai casi coperti.

Confronta questo con un programma per computer, che deve fornire un output "corretto" per una gamma di possibili input. Raramente è possibile elencare tutti gli input e provarli tutti. Peggio ancora, supponiamo che il programma interagisca con un essere umano e consenta ai suoi input di modificare il funzionamento? Gli esseri umani sono notoriamente imprevedibili e il numero di possibili input per un programma ragionevolmente ampio con interazione umana cresce a un ritmo prodigioso. È necessario provare a prevedere tutti i diversi modi in cui un programma potrebbe essere utilizzato e provare a far funzionare tutti questi casi d'uso o almeno fallire in modo ragionevole, quando il fallimento è l'unica opzione. E questo presuppone che tu sappia anche come dovrebbe funzionare in tutti quegli oscuri casi d'angolo.

Infine, un programma di grandi dimensioni non può davvero essere paragonato a una singola prova, anche se complessa. Un programma di grandi dimensioni è probabilmente più simile alla raccolta e alla revisione di una piccola biblioteca di letteratura, alcuni dei quali potrebbero contenere errori che è necessario aggirare. Per i programmi più sulla scala di una singola prova, che potrebbe essere una piccola implementazione di algoritmo, diciamo, ingegneri del software con esperienza possono / fare completarli senza fare errori, specialmente quando usano strumenti moderni che impediscono / risolvono errori banali comuni (come errori di ortografia ) che equivalgono a problemi iniziali che risolveresti nella correzione di bozze.


14
+1 per il tuo ultimo paragrafo. Mentre le prove matematiche sono in linea di principio costruite una sopra l'altra, di solito le basi sono ben comprese, l'analogo delle librerie di computer (anche se hanno anche dei bug ...) e la prova effettiva non è troppo lunga. Al contrario, il software di consumo è lungo e complicato, e quindi ha molte più opportunità di fallire.
Yuval Filmus,

6
In pratica, l'altro problema con il software consumer è che il comportamento "corretto" è spesso mal definito in anticipo e quindi ciò che prima era corretto in seguito diventa sbagliato. Sarebbe come provare a scrivere una prova solo per scoprire che le persone hanno deciso di cambiare gli assiomi. Puoi sistemarlo in notazione, giusto?
Dan Bryant,

2
@DanBryant Quella situazione accade in matematica. In particolare, le definizioni dei termini cambiano nel tempo e sono spesso ambigue anche nel modo giusto. "Prove e confutazioni" di Imre Lakatos lo descrive con il termine "poligono". Una cosa simile è successa con la "funzione" e, in misura minore, con "integrale". Ancora oggi, la "categoria" non è inequivocabile e le prove e i teoremi possono fallire a seconda di cosa intendi esattamente.
Derek Elkins,

25

Dicono che il problema con i computer è che fanno esattamente quello che dici loro.

Penso che questo potrebbe essere uno dei tanti motivi.

Si noti che, con un programma per computer, lo scrittore (tu) è intelligente ma il lettore (CPU) è stupido.
Ma con una prova matematica, lo scrittore (tu) è intelligente e anche il lettore (revisore) è intelligente.

Ciò significa che non puoi mai permetterti di entrare in una situazione "beh, sai cosa intendo " con un computer. Fa esattamente quello che gli dici, senza conoscere le tue intenzioni.

Ad esempio, supponiamo che questo sia un passaggio in alcune prove:

x2+4x+3x+3=(x+1)(x+3)x+3=x+1

x2+4x+3x+3x=3


3
Bella risposta! tranne che come computer, mi oppongo al tuo uso della parola "inutilmente". ;) [Supponiamo che questo sia stato solo un passo in una prova più ampia volta a dimostrare che -xè composito. Il fatto che questo passaggio sia sbagliato quando -x = 3è molto rilevante per la correttezza della prova completata!]
Quuxplusone,

@Quuxplusone: = P
Mehrdad,

I computer possono usare anche la matematica simbolica e le regole di riscrittura non deterministica, è solo che i linguaggi che usiamo come C ++ sono tutti di livello molto basso e basati su una tecnologia antica (il C aveva meno funzioni rispetto all'Algol 60, per esempio). Le uniche eccezioni sono i linguaggi di verifica / verifica come Idris / Agda, Lisp con risolutori simbolici e Mathematica. ja.wolframalpha.com/input/…
aoeu256,

23

Un problema che penso non sia stato affrontato nella risposta di Yuval, è che sembra che tu stia confrontando diversi animali.

nn!

La verifica delle proprietà semantiche dei programmi è indecidibile (teorema di Rice) e, analogamente, è anche impossibile verificare se un'affermazione nella logica del predicato del primo ordine è vera. Il punto è che non vi è alcuna reale differenza nella durezza dal modo in cui si stanno osservando i problemi. D'altra parte, possiamo ragionare sulle proprietà sintattiche dei programmi (compilatori), e questo è analogo al fatto che possiamo verificare le prove. I bug (il codice non fa quello che voglio) sono semantici, quindi dovresti confrontarli con la loro controparte corretta.

Rafforzerò Yuval e dirò che interi campi sono cresciuti con la motivazione di scrivere prove matematiche che possono essere scritte e verificate in un sistema formale, quindi anche il processo di verifica non è affatto banale.


18

Cosa c'è di così diverso nello scrivere prove matematiche impeccabili e nel scrivere codice informatico impeccabile che lo rende così il primo è molto più trattabile del secondo?

Credo che i motivi principali siano l' idempotenza (fornisce gli stessi risultati per gli stessi input) e l' immutabilità (non cambia).

E se una prova matematica potesse dare risultati diversi se fosse stata letta un martedì o quando l'anno avanzava fino al 2000 dal 1999? E se una parte di una prova matematica fosse quella di tornare indietro di alcune pagine, riscrivere alcune righe e ricominciare da quel punto?

Sono sicuro che una tale prova sarebbe quasi incline ai bug come un normale segmento di codice del computer.

Vedo anche altri fattori secondari:

  1. I matematici di solito sono molto più istruiti prima di tentare di scrivere una prova significativa / pubblicabile. 1/4 di sviluppatori professionisti omonimi hanno iniziato a scrivere codice meno di 6 anni fa (vedi l' indagine SO 2017 ), ma presumo che la maggior parte dei matematici abbia oltre un decennio di educazione matematica formale.
  2. Le prove matematiche sono raramente mantenute allo stesso livello di controllo del codice del computer. Un singolo errore di battitura può / romperà un programma, ma dozzine di errori di battitura potrebbero non essere sufficienti a distruggere il valore di una prova (solo la sua leggibilità).
  3. Il diavolo è nei dettagli e il codice del computer non può saltare i dettagli. Le prove sono libere di saltare passaggi considerati semplici / di routine. Ci sono alcuni zuccheri sintattici disponibili nelle lingue moderne, ma questi sono hard-coded e abbastanza limitati in confronto.
  4. La matematica è più antica e ha una base / un nucleo più solidi. Esistono sicuramente molti sottocampi nuovi e brillanti in matematica, ma la maggior parte dei principi fondamentali sono in uso da decenni. Questo porta alla stabilità. Dall'altro lato, i programmatori non sono ancora d'accordo sulla metodologia di codifica di base (basta chiedere informazioni sullo sviluppo di Agile e sul suo tasso di adozione).

Vale la pena ricordare che l'equivalente della programmazione di "indempotenza" è la purezza funzionale , che è riconosciuta e supportata in alcuni linguaggi come Haskell.
Pharap,

12

Sono d'accordo con ciò che Yuval ha scritto. Ma hanno anche una risposta molto più semplice: in pratica i software in genere gli ingegneri non provano nemmeno a verificare la correttezza dei loro programmi, semplicemente non lo fanno, in genere non scrivono nemmeno le condizioni che definiscono quando il programma è corretto.

Ci sono varie ragioni per questo. Uno è che la maggior parte degli ingegneri del software non ha le competenze per formulare chiaramente i problemi matematicamente né sa come scrivere prove di correttezza.

Un altro è che definire le condizioni di correttezza per un sistema software complesso (specialmente uno distribuito) è un compito molto difficile e che richiede tempo. Ci si aspetta che abbiano qualcosa che sembra funzionare nel giro di poche settimane.

Un altro motivo è che la correttezza di un programma dipende da molti altri sistemi scritti da altri che ancora una volta non hanno una semantica chiara. Esiste una legge di Hyrum che in sostanza dice se la tua biblioteca / servizio ha un comportamento osservabile (non parte del suo contratto) qualcuno alla fine dipenderà da esso. Ciò significa essenzialmente che l'idea di sviluppare software in forma modulare con contratti chiari come i lemmi in matematica non funziona nella pratica. Peggiora le lingue in cui viene usata la riflessione. Anche se un programma è corretto oggi, potrebbe fallire domani quando qualcuno fa qualche banale refactoring in una delle sue dipendenze.

In pratica ciò che accade di solito è che hanno dei test. I test agiscono come previsto dal programma. Ogni volta che viene trovato un nuovo bug, aggiungono dei test per rilevarlo. Funziona in qualche misura, ma non è una prova di correttezza.

Quando le persone non hanno le competenze per definire la correttezza, né per scrivere programmi corretti, né se lo si aspetta e farlo è piuttosto difficile, non sorprende che i software non siano corretti.

Ma nota anche che alla fine, in posti migliori, l'ingegneria del software viene eseguita mediante la revisione del codice. Questo è l'autore di un programma deve convincere almeno un'altra persona che il programma funziona correttamente. Questo è il punto in cui vengono formulate argomentazioni informali di alto livello. Ma di solito non accade nulla di simile a una chiara definizione rigorosa di correttezza o prova di correttezza.

In matematica le persone sono focalizzate sulla correttezza. Nello sviluppo del software ci sono molte cose di cui un programmatore deve preoccuparsi e ci sono dei compromessi tra di loro. Avere un software privo di bug o anche una buona definizione di correttezza (con requisiti che cambiano nel tempo) è l'ideale, ma deve essere scambiato con altri fattori e uno dei più importanti tra loro è il tempo impiegato per svilupparlo sviluppatori. Quindi, in pratica in posti migliori, l'obiettivo e i processi stanno mitigando il rischio di bug per quanto possibile, piuttosto che rendere il software privo di bug.


In realtà non sono sicuro di chi stia peggio tra programmatori e matematici formalmente (cioè in modo controllato da una macchina) formulando specifiche di correttezza e dimostrando che il codice è corretto per, diciamo, un programma 10KLOC o più grande. Da un lato, hai perfettamente ragione sul fatto che la maggior parte dei programmatori non ha abilità di dimostrazione del teorema ben sviluppate. D'altra parte, le prove formali di grandi dimensioni sono come programmi di grandi dimensioni e richiedono essenzialmente competenze di ingegneria del software per la gestione. Sono completamente fiducioso che qualsiasi prova informale di correttezza per un tale programma non avrebbe alcuna speranza di avere ragione.
Derek Elkins,

Può essere. In ogni caso e solo per chiarire, non sto prendendo in considerazione prove formali nella mia risposta, solo prove informali al livello che vediamo dire nei documenti sugli algoritmi.
Kaveh,

11

Ci sono già molte buone risposte ma ci sono ancora più ragioni per cui la matematica e la programmazione non sono le stesse.

1 Le prove matematiche tendono ad essere molto più semplici dei programmi per computer. Considera i primi passi di una prova ipotetica:

Lascia che sia un numero intero

Sia b un numero intero

Sia c = a + b

Finora la prova va bene. Trasformiamolo nei primi passi di un programma simile:

Consenti a = input ();

Let b = input ();

Sia c = a + b;

Abbiamo già una miriade di problemi. Supponendo che l'utente abbia effettivamente inserito un numero intero, dobbiamo verificare i limiti. È un maggiore di -32768 (o qualunque sia il min int sul vostro sistema è)? È un meno di 32767? Ora dobbiamo controllare la stessa cosa per b . E poiché abbiamo aggiunto una e B del programma non è corretto a meno che a + bè maggiore di -32768 e inferiore a 32767. Sono 5 le condizioni separate che un programmatore deve preoccuparsi che un matematico possa ignorare. Non solo il programmatore deve preoccuparsi di loro, deve capire cosa fare quando una di queste condizioni non è soddisfatta e scrivere il codice per fare tutto ciò che ha deciso è il modo di gestirle. La matematica è semplice. La programmazione è difficile.

2 L'interrogante non dice se si sta riferendo a errori di compilazione o errori di runtime, ma i programmatori generalmente non si preoccupano degli errori di compilazione. Il compilatore li trova e sono facili da risolvere. Sono come errori di battitura. Con quale frequenza le persone digitano più paragrafi senza errori la prima volta?

3 Formazione.Fin dalla tenera età ci viene insegnato a fare matematica e affrontiamo continuamente le conseguenze di piccoli errori. Un matematico qualificato ha dovuto iniziare a risolvere i problemi di algebra in più fasi di solito nella scuola media e ha dovuto fare dozzine (o più) di tali problemi ogni settimana per un anno. Un singolo segno negativo lasciato cadere ha causato un intero problema per essere sbagliato. Dopo l'algebra i problemi sono diventati più lunghi e più difficili. I programmatori, d'altra parte, di solito hanno una formazione molto meno formale. Molti sono autodidatti (almeno inizialmente) e non hanno ricevuto una formazione formale fino all'università. Anche a livello universitario, i programmatori devono frequentare alcune classi di matematica mentre i matematici probabilmente seguono una o due lezioni di programmazione.


10

Mi piace la risposta di Yuval, ma ho voluto rifarla per un po '. Un motivo per cui potresti trovare più semplice scrivere prove matematiche potrebbe ridursi a quanto è platonica l'ontologia matematica. Per vedere cosa intendo, considera quanto segue:

  • Le funzioni in matematica sono pure (l'intero risultato della chiamata a una funzione è completamente incapsulato nel valore di ritorno, che è deterministico e calcolato completamente dal valore di input).
  • La matematica non ha mutazione o riassegnazione (quando è necessario modellare tali cose, vengono utilizzate funzioni e sequenze).
  • La matematica è referenzialmente trasparente (es. Nessun puntatore, nessuna nozione di chiamata per nome vs chiamata per valore) e gli oggetti matematici hanno una semantica di uguaglianza estensiva (se "due" cose sono uguali in ogni modo osservabile, allora sono in effetti la stessa cosa).

Mentre è discutibile se le restrizioni di cui sopra rendano più semplice la scrittura di un programma, penso che ci sia un ampio consenso sul fatto che le restrizioni di cui sopra rendono più facile il ragionamento su un programma. La cosa principale che fai quando scrivi una prova di matematica è la ragione della prova che stai attualmente scrivendo (poiché, a differenza della programmazione, non devi mai duplicare gli sforzi in matematica poiché le astrazioni sono gratuite), quindi in genere vale la pena insistere sul sopra le restrizioni.


7

Le prove matematiche fondamentali non equivalgono a un'applicazione del mondo reale, progettata per soddisfare i bisogni umani vivi.

Gli umani cambieranno i loro desideri, bisogni e requisiti su quella che è forse una base quotidiana nel regno dei programmi per computer.

Cosa c'è di così diverso nello scrivere prove matematiche impeccabili e nel scrivere codice informatico impeccabile che lo rende così il primo è molto più trattabile del secondo?

Con un requisito tanto chiaro quanto un problema matematico, si potrebbe scrivere un programma impeccabile. Dimostrare che l'algoritmo di Dijkstra può trovare il percorso più breve tra due punti su un grafico non è lo stesso che implementare un programma che accetta input arbitrari e trovare i punti più brevi tra due punti qualsiasi in esso.

Ci sono problemi di memoria, prestazioni e hardware da gestire. Vorrei che non potessimo pensare a quelli quando scriviamo algoritmi, che potremmo usare costrutti puri e funzionali per gestirlo, ma i programmi per computer vivono nel "reale" mondo dell'hardware mentre la prova matematica risiede nella ... "teoria".


O, per essere più concisi :

inserisci qui la descrizione dell'immagine


4

Guardandolo da un'altra prospettiva, in un ambiente non accademico spesso si riduce al denaro.

Come affermano bene gli altri post, la matematica è una singola specifica astratta, quindi una prova deve funzionare coerentemente all'interno di quella specifica per essere provata. Un programma per computer può operare su molte implementazioni della specifica astratta della matematica, vale a dire il modo in cui un linguaggio o un produttore di hardware implementa la matematica in virgola mobile può essere leggermente diverso da un altro, il che può causare lievi fluttuazioni nei risultati.

Pertanto, "provare" un programma per computer prima di scriverlo comporterebbe quindi provare la logica a livello hardware, a livello di sistema operativo, a livello di driver, linguaggio di programmazione, compilatore, forse interprete e così via, per ogni possibile combinazione di hardware che il programma potrebbe essere plausibilmente eseguito e qualsiasi dato concepibile che potrebbe ingerire. Probabilmente troverai questo livello di preparazione e comprensione nelle missioni spaziali, nei sistemi di armi o nei sistemi di controllo dell'energia nucleare, dove il fallimento significa decine di miliardi di dollari persi e potenzialmente molte vite perse, ma non molto altro.

Per il tuo programmatore e / o azienda "di tutti i giorni", è molto, molto più conveniente accettare un certo livello di precisione nel codice per lo più corretto e vendere un prodotto utilizzabile, e gli sviluppatori possono correggere in modo retroattivo i bug che vengono scoperti durante utilizzo.


3
Sembra che tu abbia una visione ristretta di cosa sia la matematica e una visione troppo espansiva di ciò che "prova" comporta un programma per computer. Non è necessario dimostrare che l'intero sistema è corretto per dimostrare che un programma è corretto, è sufficiente dimostrare che è corretto presupponendo che gli altri componenti soddisfino le loro specifiche. In caso contrario, non è colpa del tuo programma. D'altra parte, se il tuo programma si interrompe perché dipende da dettagli che non fanno parte delle specifiche di tali componenti, ad esempio variazioni delle implementazioni di IEEE754, allora è colpa tua.
Derek Elkins,

Commento equo. Probabilmente sto abusando della terminologia in quanto non è il mio background accademico. Anche se ritengo che supporre che altri componenti siano impeccabili non sia una cosa saggia da fare, a causa dei miei commenti precedenti.
navigator_

4

Penso che il tuo ragionamento sia valido, ma il tuo contributo non lo è. Le prove matematiche semplicemente non sono più tolleranti ai guasti rispetto ai programmi, se entrambi sono scritti da umani. Dijkstra era già stato citato qui, ma offrirò un preventivo aggiuntivo.

Tuttavia, dobbiamo organizzare i calcoli in modo tale che i nostri poteri limitati siano sufficienti a garantire che il calcolo stabilisca l'effetto desiderato. Questa organizzazione include la composizione del programma e ci troviamo di fronte al prossimo problema di dimensioni, vale a dire. la lunghezza del testo del programma, e dovremmo dare a questo problema anche un riconoscimento esplicito. Dobbiamo essere consapevoli del fatto che la misura in cui possiamo leggere o scrivere un testo dipende molto dalle sue dimensioni. [...]

È nello stesso umore che vorrei attirare l'attenzione del lettore sul fatto che la "chiarezza" abbia pronunciato aspetti quantitativi, un fatto che molti matematici, curiosamente, sembrano non conoscere. Un teorema che afferma la validità di una conclusione quando sono soddisfatte dieci pagine piene di condizioni non è certo uno strumento conveniente, poiché tutte le condizioni devono essere verificate ogni volta che si fa appello al teorema. Nella geometria euclidea, il teorema di Pitagora vale per tre punti A, B e C tali che attraverso A e C una linea retta può essere tracciata ortogonalmente a una linea retta attraverso B e C. Quanti matematici apprezzano che il teorema rimanga applicabile quando alcuni o tutti i punti A, B e C coincidono? tuttavia questo sembra in gran parte responsabile della comodità con cui il Teorema di Pitagora può essere usato.

Riassumendo: in quanto essere umano lento ho una testa molto piccola e farei meglio a imparare a conviverci e a rispettare i miei limiti e dare loro pieno credito, piuttosto che cercare di ignorarli, poiché l'ultimo sforzo vano sarà punito dal fallimento.

Questo è leggermente modificato negli ultimi tre paragrafi del primo capitolo della Programmazione strutturata di Dijkstra.

Forse per riformulare questo, applicare meglio alla tua domanda: la correttezza è in gran parte una funzione della dimensione della tua prova. È molto difficile stabilire la correttezza di lunghe prove matematiche (molte "prove" pubblicate vivono nel limbo dell'incertezza poiché nessuno le ha effettivamente verificate). Ma, se si confronta la correttezza di programmi banali con prove banali, probabilmente non c'è alcuna differenza evidente. Tuttavia, gli assistenti di correzione automatici (in senso lato, il compilatore Java è anche un assistente di correzione), consentono ai programmi di vincere automatizzando molte basi.


Cosa intendi con "lunghe prove matematiche"? La dimostrazione del teorema minore grafico è piuttosto lunga, ma non è contestata da nessuno. Il teorema di Feit-Thompson ha una prova piuttosto lunga, ma non è mai stato davvero in un limbo. Come si confrontano le lunghezze di prove e programmi? Numero di parole? Non ci sono davvero differenze evidenti tra prove e programmi quando si confrontano prove e programmi di complessità (lunghezza) simili?
Yuval Filmus,

@YuvalFilmus proprio come nella citazione: dieci pagine di affermazioni sono lunghe per gli umani. Come giudico la durata di un programma? Bene, Dikstra ha offerto una metrica: la lunghezza del suo testo. Penso che potrebbe essere troppo semplicistico, ma è comunque una buona euristica. Ci sono altre metriche più interessanti, come, ad esempio, la complessità ciclomatica
wvxvw,

3

Come altre risposte hanno toccato nelle loro risposte (voglio elaborare), ma gran parte del problema è l'uso della biblioteca. Anche con una documentazione perfetta (comune come codice senza errori), è impossibile trasferire la conoscenza completa di una libreria a tutti i programmatori che usano la libreria. Se il programmatore non capisce perfettamente la propria libreria, potrebbe commettere errori durante l'utilizzo. A volte questi possono causare bug critici che vengono scoperti quando il codice non funziona. Ma per bug minori, questi potrebbero passare inosservati.

Una situazione simile sarebbe se un matematico usasse prove e lemmi esistenti senza comprenderle appieno; le loro prove sarebbero probabilmente imperfette. Sebbene ciò possa suggerire una soluzione è imparare perfettamente ogni libreria che si utilizza; questo richiede praticamente molto tempo e può richiedere una conoscenza del dominio che il programmatore non ha (conosco molto poco il sequenziamento del DNA / la sintesi proteica; tuttavia posso lavorare con questi concetti usando le librerie).

Più sinteticamente, l'ingegneria del software (ingegneria in generale in realtà) si basa sull'incapsulamento di diversi livelli di astrazione per consentire alle persone di concentrarsi su aree più piccole del problema in cui si specializzano. Ciò consente alle persone di sviluppare competenze nella loro area, ma richiede anche un'eccellente comunicazione tra ogni strato. Quando quella comunicazione non è perfetta, causa problemi.


3
Aspetta, cosa ti fa pensare che i matematici "comprendano appieno" le prove e i lemmi che usano? Non sono sicuro della differenza tra matematici e programmatori che stai cercando di dimostrare qui.
Derek Elkins,

3

Proverò ad essere originale dopo tutte quelle grandiose risposte.

I programmi sono prove

L' isomorfismo di Curry-Howard ci dice che i tipi nel tuo programma sono i teoremi e il codice attuale ne è la prova.

Certo, questa è una visione molto astratta e di alto livello. Il problema che probabilmente intendi è che scrivere un codice tipico è più difficile perché diventa di livello troppo basso. Nella maggior parte dei casi "devi dire alla macchina cosa fare". Oppure, per guardarlo da un'altra parte: i matematici sono davvero bravi nell'astrazione.

Come nota a margine: "La musica dei flussi" è uno dei ponti più belli tra entrambi. Esso stabilisce fondamentalmente le cose per essere in grado di dire "Io voglio questo in quel modo", e la macchina fa magicamente questo esattamente, se lo desideri.


Non vedo se questo risolve la questione. L'OP non ha dato alcuna indicazione sul fatto che stessero parlando di linguaggi di programmazione con sistemi di tipo potenti e penso che significhino sistemi di tipo più generici. Quindi Curry-Howard è piuttosto banale in questo caso.
6005

So che è un po 'inverosimile per C o cose simili. Ma il mio punto è: la matematica è più vicina di quanto possa pensare un tipico principiante CS!
Oleg Lobachev il

1
Sembra che tu sia un "osservatore distratto" dell'isomorfismo di Curry-Howards, a cui ho fatto riferimento nella mia risposta. Anche se abbiamo un isomorfismo tra programmi e prove, non ne consegue che l'atto di scrivere programmi e scrivere prove sia del tutto simile. In effetti, può anche accadere che tutti i programmi "interessanti" o "tipici" non corrispondano a una dimostrazione tipica e viceversa.
Lucertola discreta

@Discretelizard Non è evidentemente il caso che i programmi "interessanti" non corrispondano a una "prova tipica". Ecco un esempio in cui prendo la "prova tipica" di qualcuno e produco un (schizzo) di un programma innegabilmente interessante (qualcosa strettamente legato all'eliminazione gaussiana). Equipaggiato con tipi opportunamente precisi, penso che la maggior parte dei programmi "interessanti" sarebbero utili lemmi o teoremi, ma molte prove (costruttive) non hanno un reale significato computazionale - stanno solo verificando le condizioni secondarie - anche se molti lo fanno.
Derek Elkins,

3

Nessuna delle tante altre risposte indica quanto segue. Le prove matematiche operano su sistemi di calcolo immaginari che hanno memoria infinita e potenza di calcolo infinita. Pertanto possono contenere numeri arbitrariamente grandi con precisione infinita e non perdere alcuna precisione in alcun calcolo.

π


2
"Le prove matematiche operano su sistemi di calcolo immaginari che hanno memoria infinita e potenza di calcolo infinita." La maggior parte delle prove matematiche "opera" su sistemi algebrici formali, ad esempio i numeri reali (dove abbiamo "precisione infinita"). Questo può essere fatto anche nei programmi: ci sono i cosiddetti sistemi di algebra dei computer (CAS) che fanno esattamente questo! Inoltre, interi campi della matematica si preoccupano del fatto che non possiamo rappresentare tutti i numeri reali esattamente come numeri a virgola mobile finiti. Penso che tu stia facendo una distinzione tra matematica e programmazione dove non ce n'è.
Lucertola discreta

1
@Discretelizard, sì, esistono pacchetti speciali con precisione arbitraria, ma anche in questo caso, la memoria disponibile limiterà l'effettiva precisione ottenibile. Inoltre sono pacchetti speciali . Solo una piccola parte della programmazione viene eseguita con tali pacchetti, e principalmente in un ambiente accademico.
crobar,

π

@Discretelizard, penso che il mio punto sia ancora valido, la maggior parte dei programmatori non utilizza tali sistemi CAS. Sono troppo lenti per la programmazione nel mondo reale. La maggior parte della programmazione prevede fondamentalmente operazioni su numeri di precisione limitati. I linguaggi principali sono C, C ++, Python, Java ecc. Nessuno usa la rappresentazione in stile CAS per impostazione predefinita (anche se i pacchetti per farlo potrebbero essere creati in essi). Il tuo controesempio è un piccolo sottogruppo di nicchia di linguaggi / sistemi di computer.
crobar,

2
@crobar Il problema con la tua risposta è che la stragrande maggioranza dei bug rilevati non è dovuta a errori in virgola mobile o overflow di numeri interi (anche se quelli contribuiscono con un numero decente, e quegli aspetti rendono decisamente più improbabile la piena correttezza di un programma). Si potrebbe, tuttavia, affermare più genericamente che i matematici mancano di molte delle preoccupazioni dei programmatori come prestazioni, time-to-market, manutenibilità e una capacità limitata di modificare i requisiti se si rivelano troppo impegnativi.
Derek Elkins,

3

Non è. Le prove matematiche sono esattamente buggy per natura, è solo che i loro lettori sono più permissivi di un compilatore. Allo stesso modo, i lettori di un programma per computer sono facilmente ingannati nel credere che sia corretto, almeno fino a quando non provano a eseguirlo.

Ad esempio, se proviamo a tradurre una prova matematica in un linguaggio formale come ZFC, conterrà anche dei bug. Questo perché queste prove possono richiedere molto tempo, quindi siamo costretti a scrivere un programma per generare la prova. Poche persone si mettono nei guai, a loro rischio e pericolo, sebbene vi siano ricerche attive sulla formalizzazione delle prove fondamentali.

E infatti, la matematica può ottenere BSOD! Non sarebbe la prima volta!

inserisci qui la descrizione dell'immagine

Questa idea ortodossa secondo cui tutte le prove matematiche che sono state sufficientemente verificate siano fondamentalmente corrette o possono essere corrette è la stessa che motiva il tuo progetto software al lavoro: finché resteremo sulla roadmap, elimineremo tutti i bug e il funzionalità complete: è un processo iterativo che porta a un prodotto finale definito.

Ecco il rovescio della medaglia. Senti, abbiamo già ottenuto i finanziamenti, convalidato il concetto di business, tutti i documenti sono qui per essere letti. Abbiamo solo bisogno che tu lo esegua ed è una cosa certa!

Non sentiamoci troppo dispiaciuti anche per Hilbert , sapeva in che cosa stava entrando. Sono solo affari.

Se vuoi essere veramente sicuro, prendi tutto caso per caso e trai le tue conclusioni!


3

Vedo due importanti motivi per cui i programmi sono più soggetti a errori rispetto alle prove matematiche:

1: I programmi contengono variabili o oggetti dinamici che cambiano nel tempo, mentre gli oggetti matematici nelle prove sono normalmente statici. Pertanto, la notazione in matematica può essere utilizzata come supporto diretto del ragionamento (e se a = b, questo rimane il caso) in cui ciò non funziona nei programmi. Inoltre, questo problema peggiora molto quando i programmi sono paralleli o hanno più thread.

2: la matematica spesso assume oggetti definiti in modo relativamente accurato (grafici, varietà, anelli, gruppi, ecc.) Mentre la programmazione si occupa di oggetti molto disordinati e piuttosto irregolari: aritmetica di precisione finita, pile finite, conversioni di caratteri interi, puntatori, immondizia che necessita di raccolta , ecc ... La raccolta di condizioni rilevanti per la correttezza è quindi molto difficile da tenere a mente.


3

Dovresti distinguere due diverse "categorie":

  • pseudo-prove (o pseudo-codice): questo è ciò che vedi nei libri. È scritto in linguaggio naturale (ad es. In inglese). Questo è ciò che dovresti usare per imparare la matematica (o algoritmi).
  • prove formali (o codice formale): le scrivi quando hai bisogno che la prova (o il codice) sia verificabile meccanicamente (o eseguibile). Tale rappresentazione non richiede alcuna "intelligenza umana". Può essere verificato (o eseguito) meccanicamente, seguendo alcuni passaggi predefiniti (di solito eseguiti dai computer oggi).

Usiamo pseudo-codice da migliaia di anni (es. Algoritmo Euclids). Scrivere codice formale (in linguaggi formali come C o Java) è diventato estremamente popolare e utile dopo l'invenzione dei computer. Ma, purtroppo, le prove formali (in linguaggi formali come Principia Mathematica o Metamath) non sono molto popolari. E poiché oggi tutti scrivono pseudo-prove, le persone spesso discutono di nuove prove. Gli errori possono essere trovati anni, decenni o addirittura secoli dopo l'effettiva "dimostrazione".


3

Non riesco a trovare il riferimento, ma penso che Tony Hoare abbia detto una volta qualcosa come segue: la differenza tra il controllo di un programma e il controllo di una prova è che una prova può essere controllata due righe alla volta.

In una parola: località.

Le prove sono scritte in modo che possano essere facilmente verificate. I programmi sono scritti in modo da poter essere eseguiti. Per questo motivo, i programmatori di solito tralasciano informazioni che potrebbero essere utili a qualcuno che controlla il programma.

Considera questo programma, dove x è di sola lettura

    assume x >= 0
    p := 0 ;
    var pp := 0 ;
    while( x >= pp + 2*p + 1 ) 
    {
        var q := 1 ;
        var qq := q ;
        var pq := p ;
        while(  pp + 4*pq + 4*qq <= x )
        {
            q, pq, qq := 2*q, 2*pq, 4*qq ;
        }
        p, pp := p + q, pp + 2*pq + qq ;
    }
    assert  p*p <= x < (p+1)*(p+1)

È facile da eseguire, ma difficile da verificare.

Ma se aggiungo di nuovo le asserzioni mancanti, puoi controllare il programma localmente controllando semplicemente che ogni sequenza di assegnazioni sia corretta con il rispetto delle sue pre e postcondizioni e che, per ogni ciclo, la postcondizione del ciclo sia implicita dal invariante e negazione della guardia ad anello.

    assume x >= 0
    p := 0 ;
    var pp := 0 ; 
    while( x >= pp + 2*p + 1 ) 
        invariant p*p <= x 
        invariant pp == p*p
        decreases x-p*p 
    {
        var q := 1 ;
        var qq := q ; 
        var pq := p ; 
        while(  pp + 4*pq + 4*qq <= x )
            invariant (p+q)*(p+q) <= x
            invariant q > 0 
            invariant qq == q*q 
            invariant pq == p*q 
            decreases x-(p+q)*(p+q)
        {
            q, pq, qq := 2*q, 2*pq, 4*qq ;
        }
        assert (p+q)*(p+q) <= x and pp==p*p and pq==p*q and qq==q*q and q>0
        p, pp := p + q, pp + 2*pq + qq ;
    }
    assert  p*p <= x < (p+1)*(p+1)

Tornando alla domanda originale: perché scrivere prove matematiche è più a prova di errore che scrivere un codice per computer? Poiché le prove sono progettate per essere facilmente verificate dai loro lettori, sono facilmente controllate dai loro autori e quindi gli autori in allerta tendono a non commettere (o almeno a conservare) errori logici nelle loro prove. Quando programmiamo, spesso non riusciamo a scrivere il motivo per cui il nostro codice è corretto; il risultato è che sia difficile per i lettori che per l'autore di un programma controllare il codice; il risultato è che gli autori commettono (e quindi mantengono) errori.

Ma c'è speranza. Se, quando scriviamo un programma, annotiamo anche il motivo per cui pensiamo che il programma sia corretto, possiamo quindi controllare il codice mentre lo scriviamo e quindi scrivere meno codice errato. Ciò ha anche il vantaggio che altri possono leggere il nostro codice e verificarlo da soli.


2

Potremmo chiedere se è più difficile in pratica , o in linea di principio , scrivere prove o scrivere codice.

In pratica, dimostrare è molto più difficile della codifica. Pochissime persone che hanno preso due anni di matematica a livello universitario possono scrivere prove, anche banali. Tra le persone che hanno preso due anni di CS a livello universitario, probabilmente almeno il 30% può risolvere FizzBuzz .

Ma in linea di principio , ci sono ragioni fondamentali per cui è il contrario. Le prove possono, almeno in linea di principio, essere verificate per correttezza attraverso un processo che non richiede alcun giudizio o comprensione. I programmi non possono - non possiamo nemmeno dire, attraverso un processo prescritto, se un programma si fermerà.


3
Due anni di livello universitario di matematica non significa due anni di concentrato sulla scrittura di prove (o spendere qualsiasi tempo a scrivere le prove). Detto questo, la mia impressione è che è comune per i middle / primi classi geometria delle scuole superiori per includere le prove, così apparentemente si può aspettarsi anche 13 anni per essere in grado di scrivere semplici prove con meno di un anno scolastico di istruzione sul argomento. Anche i calcoli algebrici passo-passo sono essenzialmente prove. Penso che tu stia mettendo la barra del "banale" per la programmazione troppo bassa e per dimostrarti troppo alta.
Derek Elkins,

3
Potremmo scrivere programmi allo stesso modo. Potresti immaginare un requisito secondo cui ogni funzione / procedura che scrivi deve fornire una specifica formale e una prova (in Coq, diciamo) che soddisfi le specifiche. Esistono quindi modi per verificare la correttezza di tale prova in un modo che non richiede alcun giudizio o comprensione.
DW

@DW: stai supponendo che (1) il comportamento desiderato possa essere completamente specificato in tutti i casi, (2) esiste la prova necessaria (ovvero, il problema non è indecidibile) e (3) se la prova esiste, allora noi posso trovarlo. Penso che tutte e tre queste ipotesi siano false in almeno alcuni casi (probabilmente quasi tutti i casi). Per quanto riguarda 3, nota che sebbene alcune prove possano essere facili, molte prove sono molto difficili da trovare.
Ben Crowell,

@DerekElkins: la mia affermazione che pochissimi studenti universitari possono scrivere prove anche banali si basa sulla mia esperienza con i miei studenti. Questo è in un college della comunità, quindi YMMV. Il fatto che alcune lezioni di geometria del liceo includano una pesante dose di bozze di bozze non si traduce nel fatto che tutti gli studenti universitari possono scrivere prove. Dovrebbero anche sapere come fare l'algebra di base, ma nella mia scuola circa la metà degli studenti di matricola non può farlo, il che aiuta a spiegare perché così tanti falliscono.
Ben Crowell,

Sarebbe una buona spiegazione da aggiungere alla risposta, per spiegare perché non è possibile adottare lo stesso approccio per verificare la correttezza del programma. Generalmente (2) e (3) sono raramente un problema, sia nella pratica che in linea di principio (se non riesci a dimostrare il programma corretto, scrivi in ​​un modo diverso fino a quando non puoi dimostrarlo corretto). Comunque il tuo (1) è un punto importante, e penso che rafforzerebbe la risposta per spiegare perché ciò rende difficile fare la stessa cosa per i programmi come facciamo per le prove.
DW

2

Solo una piccola parte di affermazioni matematiche vere può essere praticamente dimostrata. Più significativamente, sarebbe impossibile costruire un insieme non banale (*) di assiomi matematici che permetterebbe di provare tutte le affermazioni vere. Se uno avesse solo bisogno di scrivere programmi per fare una piccola parte delle cose che si potevano fare con i computer, sarebbe possibile scrivere un software dimostrabilmente corretto, ma i computer sono spesso chiamati a fare cose al di là della gamma di ciò che è dimostrabilmente corretto il software può realizzare.

(*) È possibile definire un insieme di assiomi che consentirebbe di enumerare tutte le affermazioni vere e quindi provarle, ma quelle non sono generalmente molto interessanti. Mentre è possibile classificare formalmente insiemi di assiomi in quelli che sono o no, relativamente parlando, non banali, il punto chiave è che l'esistenza dimostrabile di affermazioni che sono vere ma che non possono essere provate non è un difetto in un insieme di assiomi. L'aggiunta di assiomi per rendere dimostrabili qualsiasi affermazione vera ma non dimostrabile provocherebbe la realizzazione di altre affermazioni, ma senza che possano essere dimostrate.


1
"Solo una piccola parte delle affermazioni matematiche che sono vere può essere praticamente dimostrata." - Come stai misurando la "porzione"? È sotto una certa distribuzione di probabilità? Hai prove a sostegno di questa affermazione?
DW

"I computer sono spesso chiamati a fare cose al di là della gamma di ciò che il software dimostrabilmente corretto può realizzare." - Hai qualche prova per questo? Hai un esempio? Stai sostenendo "oltre ciò che in linea di principio può essere dimostrato corretto" o "oltre ciò che possiamo ragionevolmente immaginare di provare in pratica"?
DW

@DW: Se X e Y sono affermazioni ortogonali vere ma non dimostrabili, allora per ogni affermazione dimostrabile P, ci saranno almeno due affermazioni ortogonali (P e X) e (P e Y) che sono vere ma non -provable. Quando si ha a che fare con insiemi infiniti, tale logica non dimostra necessariamente nulla, dal momento che si potrebbe usare una logica simile per mostrare che ci sono il doppio di numeri interi pari a numeri dispari, poiché per ogni numero intero dispari si possono identificare due numeri interi pari (4x) e (4x + 2) che non sono associati ad altri numeri dispari, ma ovviamente i numeri pari e dispari hanno uguale cardinalità.
supercat

@DW: La frase "piccola porzione" può quindi avere senso solo nel descrivere la frazione di affermazioni vere che può essere praticamente dimostrata, ma penso che sia utile capire che l'incapacità di provare tutte le affermazioni vere non è un "difetto". Per quanto riguarda i computer, molti campi usano abitualmente algoritmi che hanno una probabilità di guasto estremamente piccola, ma diversa da zero, e quindi li sintonizzano in modo tale che la probabilità sia accettabilmente bassa (ad esempio al di sotto di quella dell'attrezzatura colpita da una meteora). In molti casi, tuttavia, varie modalità di errore non sono indipendenti, quindi potrebbe essere sostanzialmente impossibile ...
supercat

... per determinare le probabilità di diverse combinazioni di guasti. Se si stima che la probabilità di fallimento durante un periodo arbitrario di un minuto sia di uno su 10 ^ -500, si potrebbe essere spenti di centinaia di ordini di grandezza e avere ancora un sistema affidabile, ma se uno è spento di 494 ordini di grandezza il sistema fallirebbe una volta ogni due anni.
supercat

2
  1. I programmi per computer sono testati nel mondo reale. Un delicato errore tecnico in una lunga prova matematica, che solo un numero limitato di persone può capire, ha buone probabilità di rimanere inosservato. Lo stesso tipo di errore in un prodotto software probabilmente produrrà un comportamento strano che gli utenti ordinari notano. Quindi la premessa potrebbe non essere corretta.

  2. I programmi per computer svolgono utili funzioni nel mondo reale. Non devono essere corretti al 100% per farlo e alti standard di correttezza sono piuttosto costosi. Le prove sono utili solo se dimostrano effettivamente qualcosa, quindi saltare la parte "100% corretta" non è un'opzione per i matematici.

  3. Le prove matematiche sono chiaramente definite. Se una prova è difettosa, l'autore ha commesso un errore. Molti bug nei programmi per computer si verificano perché i requisiti non sono stati comunicati correttamente o c'è un problema di compatibilità con qualcosa di cui il programmatore non ha mai sentito parlare.

  4. Molti programmi per computer non possono essere dimostrati corretti. Potrebbero risolvere problemi definiti in modo informale come riconoscere i volti. Oppure potrebbero essere come un software di previsione del mercato azionario e avere un obiettivo formalmente definito ma comportare troppe variabili del mondo reale.


2

Una grande parte della matematica come attività umana è stata lo sviluppo di linguaggi specifici del dominio in cui la verifica delle prove è facile da eseguire per un essere umano.

La qualità di una prova è inversamente proporzionale alla sua lunghezza e complessità. La lunghezza e la complessità sono spesso ridotte sviluppando una buona notazione per descrivere la situazione attuale sulla quale stiamo facendo una dichiarazione, insieme ai concetti ausiliari che interagiscono all'interno della particolare prova in esame.

Questo non è un processo facile e la maggior parte delle prove testimoniate da persone rimosse dalla prima linea della ricerca si trovano in campi matematici (come l'algebra e l'analisi) che hanno avuto centinaia, se non migliaia, di anni durante i quali la notazione di quel campo ha stato perfezionato al punto in cui l'atto di scrivere le prove sembra un gioco da ragazzi.

In prima linea nella ricerca, in particolare se lavori su problemi che non si trovano in campi con notazione ben consolidata o ben sviluppata, scommetterei che anche la difficoltà di scrivere una prova corretta si avvicina alla difficoltà di scrivere un programma corretto. Questo perché dovresti anche scrivere l'analogo di un design del linguaggio di programmazione, addestrare la tua rete neurale per compilarla correttamente, provare a scrivere la prova in questo, esaurire la memoria, provare a ottimizzare il linguaggio, itera il tuo cervello imparando la lingua, scrivi di nuovo la prova, ecc.

Per ribadire, penso che scrivere prove corrette possa affrontare la difficoltà di scrivere programmi corretti in determinate aree della matematica, ma quelle aree sono necessariamente giovani e sottosviluppate perché la nozione stessa di progresso in matematica è intimamente legata alla facilità della prova verifica.

Un altro modo di formulare il punto che voglio sottolineare è che sia i linguaggi di programmazione che la matematica sono alla fine progettati per consentire la compilazione di programmi per computer e prove. È solo che la compilazione di un programma per computer viene eseguita in un computer e garantisce la correttezza sintattica che di solito ha poco a che fare con la correttezza del programma stesso, mentre la "compilazione" di una prova viene fatta da un essere umano e garantisce la correttezza sintattica che è la stessa cosa di correttezza della prova.


1

Stai onestamente confrontando mele e arance qui. A prova di errore e senza errori non sono la stessa cosa.

Se un programma confronta i numeri 2e 3lo dice 2 is greater than 3, potrebbe essere a causa di un'implementazione errata:

# Buggy implementation
function is_a_greater_than_b(a,b):
  return b > a

Il programma è comunque privo di errori. Quando si confrontano due numeri ae b, sarà sempre in grado di dirti se bè più grande di a. Non è proprio quello che tu (il programmatore) dovevi chiedere al computer di fare.


2
Qual è la tua definizione di "errore" in un programma allora?
user56834

0

a) Perché i programmi per computer sono più grandi delle prove matematiche

a.1) Credo che ci siano più persone utilizzate durante la scrittura di programmi per computer complessi che durante la scrittura di prove matematiche. Significa che il margine di errore è maggiore.

b) Poiché i CEO / gli Azionisti si preoccupano più del denaro che della correzione di piccoli bug , nel frattempo tu (come sviluppatore) devi fare i tuoi compiti per soddisfare alcuni requisiti / scadenze / dimostrazioni

c) Perché puoi essere programmatore senza "profonda" conoscenza in scienze umane, nel frattempo sarebbe difficile farlo in matematica (credo)

Inoltre:

NASA:

Questo software è privo di bug. È perfetto, perfetto come gli esseri umani hanno raggiunto. Considera queste statistiche: le ultime tre versioni del programma - ognuna lunga 420.000 righe - avevano un solo errore ciascuna. Le ultime 11 versioni di questo software hanno totalizzato 17 errori.

Effettua l'aggiornamento del software per consentire allo shuttle di navigare con i satelliti di posizionamento globale, una modifica che coinvolge solo l'1,5% del programma o 6.366 righe di codice. Le specifiche per quella modifica sono di 2.500 pagine, un volume più spesso di una rubrica. Le specifiche per il programma attuale riempiono 30 volumi ed eseguono 40.000 pagine.

https://www.fastcompany.com/28121/they-write-right-stuff


"I programmi per computer sono più grandi delle prove matematiche" Dipende dal programma e dalle prove. E gran parte di questo sembra essere molto speculativo.
David Richerby,

@DavidRicherby bene avevo in mente cose come il teorema di Last Fermat e Apollo github.com/chrislgarry/Apollo-11 math.wisc.edu/~boston/869.pdf della NASA - e non parliamo nemmeno di sistemi operativi e così via.
Exeus il

0

Livelli di base:

Diamo un'occhiata alle cose al livello più semplice e più elementare.

Per la matematica, abbiamo:
2 + 3 = 5

L'ho imparato quando ero molto, molto giovane. Posso guardare gli elementi più elementari: due oggetti e tre oggetti. Grande.

Per la programmazione informatica, la maggior parte delle persone tende ad usare un linguaggio di alto livello. Alcune lingue di alto livello possono persino "compilare" in una delle lingue di basso livello più basse, come C. C può quindi essere tradotta in linguaggio Assembly. Il linguaggio assembly viene quindi convertito in codice macchina. Molte persone pensano che la complessità finisca qui, ma non è così: le moderne CPU prendono il codice macchina come istruzioni, ma poi eseguono il "microcodice" per eseguire effettivamente quelle istruzioni.

Ciò significa che, al livello più elementare (gestendo le strutture più semplici), ora abbiamo a che fare con il microcodice, che è incorporato nell'hardware e che la maggior parte dei programmatori non usa nemmeno direttamente, né aggiorna. In realtà, non solo la maggior parte dei programmatori non tocca il microcodice (0 livelli più alti del microcodice), la maggior parte dei programmatori non tocca il codice macchina (1 livello più alto del microcodice), e nemmeno l'Assemblea (2 livelli più alti del microcodice) ( tranne, forse, per un po 'di allenamento formale durante il college). La maggior parte dei programmatori passerà il tempo solo 3 o più livelli in più.

Inoltre, se osserviamo l'Assemblea (che è il livello più basso di quello che normalmente le persone ottengono), ogni singolo passaggio è in genere comprensibile da persone che sono state addestrate e hanno le risorse per interpretarlo. In questo senso, Assembly è molto più semplice di un linguaggio di livello superiore. Tuttavia, Assembly è così semplice che eseguire compiti complessi, o anche compiti mediocri, è molto noioso. Le lingue di livello superiore ci liberano da questo.

In una legge sulla "ingegneria inversa", un giudice ha dichiarato che anche se il codice può teoricamente essere gestito un byte alla volta, i programmi moderni coinvolgono milioni di byte, quindi alcuni tipi di record (come copie del codice) devono essere fatti proprio per tale uno sforzo per essere fattibile. (Pertanto lo sviluppo interno non è stato considerato una violazione della regola generalizzata "non fare copie" della legge sul copyright.) (Probabilmente sto pensando di creare cartucce Sega Genesis non autorizzate, ma potrei pensare a qualcosa di detto durante il caso Game Genie. )

Modernizzazione:

Esegui il codice destinato a 286s? O esegui codice a 64 bit?

La matematica utilizza fondamenti che si estendono indietro per millenni. Con i computer, le persone in genere considerano gli investimenti in qualcosa di vent'anni inutilmente inutili in termini di risorse. Ciò significa che la matematica può essere molto più accuratamente testata.

Standard di strumenti usati:

Mi è stato insegnato (da un amico che aveva una formazione di programmazione informatica più formale di me) che non esiste un compilatore C privo di bug che soddisfi le specifiche C. Questo perché il linguaggio C presuppone sostanzialmente la possibilità di utilizzare una memoria infinita ai fini di uno stack. Ovviamente, un requisito così impossibile doveva essere deviato da quando le persone cercavano di creare compilatori utilizzabili che funzionavano con macchine reali che sono un po 'più limitate in natura.

In pratica, ho scoperto che con JScript in Windows Script Host, sono stato in grado di ottenere molti buoni risultati utilizzando gli oggetti. (Mi piace l'ambiente perché il set di strumenti necessario per provare il nuovo codice è integrato nelle versioni moderne di Microsoft Windows.) Quando si utilizza questo ambiente, ho scoperto che a volte non esiste una documentazione facilmente reperibile su come funziona l'oggetto. Tuttavia, l'utilizzo dell'oggetto è così utile che lo faccio comunque. Quindi quello che farei è scrivere codice, che può essere errato come un nido di calabroni, e farlo in un ambiente piacevolmente sandbox in cui posso vedere gli effetti e conoscere i comportamenti dell'oggetto mentre interagisco con esso.

In altri casi, a volte solo dopo aver capito come si comporta un oggetto, ho scoperto che l'oggetto (in bundle con il sistema operativo) è difettoso e che è un problema noto che Microsoft ha deliberatamente deciso che non verrà risolto .

In tali scenari, faccio affidamento su OpenBSD, creato da programmatori esperti che creano regolarmente nuove versioni nei tempi previsti (due volte l'anno), con un famoso record di sicurezza di "solo due fori remoti" in oltre 10 anni? (Anche loro hanno patch errata per problemi meno gravi.) No, assolutamente. Non mi affido a un prodotto del genere con una qualità così elevata, perché sto lavorando per un'azienda che supporta le aziende che forniscono alle persone macchine che utilizzano Microsoft Windows, quindi questo è ciò su cui il mio codice deve funzionare.

Praticità / usabilità richiedono che io lavori sulle piattaforme che le persone trovano utili, e che è una piattaforma che è notoriamente dannosa per la sicurezza (anche se dai primi giorni del millennio sono stati fatti enormi miglioramenti che i prodotti della stessa azienda erano molto peggio) .

Sommario

Esistono numerosi motivi per cui la programmazione del computer è più soggetta a errori e ciò è accettato dalla comunità degli utenti di computer. In effetti, la maggior parte del codice è scritta in ambienti che non tollerano sforzi senza errori. (Alcune eccezioni, come lo sviluppo di protocolli di sicurezza, potrebbero ricevere un po 'più di impegno in questo senso.) Oltre al pensiero comunemente considerato delle ragioni per cui le aziende non vogliono investire più denaro e mancano scadenze artificiali per rendere felici i clienti, c'è l'impatto di la marcia della tecnologia che afferma semplicemente che se passi troppo tempo, lavorerai su una piattaforma obsoleta perché le cose cambieranno in modo significativo entro un decennio.

Sinceramente, ricordo di essere rimasto sorpreso da quanto fossero brevi alcune funzioni molto utili e popolari, quando ho visto del codice sorgente per strlen e strcpy. Ad esempio, strlen potrebbe essere stato qualcosa del tipo "int strlen (char * x) {char y = x; while ( (y ++)); return (yx) -1;}"

Tuttavia, i programmi per computer tipici sono molto più lunghi di così. Inoltre, molte programmazioni moderne useranno altri codici che potrebbero essere testati in modo meno approfondito o addirittura noti per essere buggy. I sistemi di oggi sono molto più elaborati di ciò che si può facilmente pensare, tranne che allontanando a mano gran parte della minutia come "dettagli gestiti da livelli inferiori".

Questa complessità obbligatoria e la certezza di lavorare con sistemi complessi e persino sbagliati, rende la programmazione informatica molto hardware da verificare rispetto a molta matematica in cui le cose tendono a ridursi a livelli molto più semplici.

Quando si scompongono le cose in matematica, si arriva a singoli pezzi che i bambini possono capire. Molte persone si fidano della matematica; almeno l'aritmetica di base (o almeno il conteggio).

Quando interrompi davvero la programmazione per vedere cosa sta succedendo, finisci con le implementazioni rotte di standard e codici rotti che vengono infine eseguiti elettronicamente e che l'implementazione fisica è solo un passo sotto il microcodice che la maggior parte degli scienziati informatici formati da università non osare toccare (se ne sono persino consapevoli).

Ho parlato con alcuni programmatori che sono al college o neolaureati che obiettano apertamente all'idea che il codice privo di bug può essere scritto. Hanno cancellato la possibilità, e sebbene riconoscano che alcuni esempi impressionanti (che sono stato in grado di mostrare) sono alcuni argomenti convincenti, considerano tali campioni come rari casi non rappresentativi e ancora respingono la possibilità di poter contare di avere standard così elevati. (Un atteggiamento molto, molto diverso rispetto alle basi molto più affidabili che vediamo in matematica.)


1
Mentre fai un bel caso per la complessità della programmazione, a malapena consideri la matematica! In effetti, sembra sottovalutare la complessità della matematica formale: "Quando si scompongono le cose in matematica, si arriva a singoli pezzi che i bambini possono capire", davvero ? Inoltre, si potrebbe dire lo stesso di una programmazione sufficientemente "di alto livello" (ad es. Scratch è progettato per i bambini). Si noti inoltre che Sebbene la specifica C completa non sia implementabile, un compilatore che supporta un sottoinsieme importante è stato mostrato formalmente corretto utilizzando prove assistite da computer.
Lucertola discreta

2+3=5

Meta note: se sei un esperto in una cosa e un principiante esperto (o inferiore) in un'altra, sei nella posizione peggiore possibile per confrontare le due.
Raffaello

Lucertola discreta - questa è la Computer Science SE. Inoltre, dopo aver letto altre risposte prima di pubblicare, mi sono sentito come se toccassero la matematica molto più dei computer. Ho sentito che la mia risposta era migliore non allungando il tempo solo per aggiungere parole che sarebbero state in gran parte ridondanti con ciò che è stato scritto altrove. /// Per quanto riguarda Scratch, l'alto livello è più complesso, non più semplice (se si considera la prospettiva di comprendere appieno tutte le parti in movimento). Da questo punto di vista, da cui stavo scrivendo, Assembly è più semplice di Scratch sopra altri livelli (con porte NAND elettroniche ancora più semplici)
TOOGAM

0

Prove matematiche descrivono "cosa" conoscenza e programmi descrivono "come" conoscenza ".

Scrivere programmi è più complesso perché il programmatore deve ragionare su tutti i diversi stati che possono sorgere e su come il comportamento del programma cambia di conseguenza. Le prove usano un ragionamento formulaico o categorico per provare cose su altre definizioni.

La maggior parte dei bug è causata da processi che entrano in stati che il programmatore non ha previsto. In un programma di solito ci sono migliaia o, in un sistema di grandi dimensioni, milioni di possibili variabili che non sono dati statici, ma che in realtà trasformano il modo in cui il programma viene eseguito. Tutti questi interagire insieme creano comportamenti impossibili da prevedere, specialmente in un computer moderno in cui vi sono strati di astrazione che cambiano sotto di te.

In una prova, non c'è stato che cambia. Le definizioni e gli oggetti della discussione sono fissi. Provare richiede di pensare al problema in generale e di considerare molti casi, ma questi casi sono fissati da definizioni.


2
Direi che le prove matematiche sono in grado di descrivere la conoscenza di "cosa": prendere ad esempio qualsiasi prova che costruisce un esempio per dimostrare l'esistenza o un metodo per calcolare un valore. Tuttavia, sono d'accordo che lo stato è qualcosa di assente nelle prove, nel senso che non esiste uno stato diverso da quello esplicitamente descritto dall'autore (o dal lettore!). È proprio questo stato che consente a un programma di fare qualcosa di cui il lettore / autore non è a conoscenza, mentre ciò è impossibile in una prova. (certo, le prove possono avere caratteristiche o risultati non intenzionali, ma c'è ancora qualche pensiero attivo richiesto per ottenerle)
Lucertola discreta

@Discretelizard Questo è un commento utile. Penso che la linea tra "cosa" e "come" sia certamente confusa. Dimostrare che un algoritmo fa quello che pensi che faccia, in realtà non sta descrivendo "come" nella mia mente, sta solo garantendo che certe proprietà siano valide. Da un punto di vista filosofico, penso che "come" la conoscenza richieda una corrispondenza con il mondo. I programmi fanno sempre quello che dici loro. Quando hai un bug quello che gli hai detto di fare non corrispondeva al mondo (quello che stai modellando). La matematica, indipendente da un'applicazione (come i problemi di fisica) sembra dipendere interamente dalla coerenza.
Justin Meiners,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.