Per provare a verificare se un algoritmo per qualche problema è corretto, il solito punto di partenza è provare a eseguire l'algoritmo manualmente su una serie di semplici casi di test - provalo su alcuni casi esemplificativi, inclusi alcuni semplici "casi angolari" ". Questa è una grande euristica: è un ottimo modo per eliminare rapidamente molti tentativi errati di un algoritmo e per capire perché l'algoritmo non funziona.
Tuttavia, quando apprendono gli algoritmi, alcuni studenti sono tentati di fermarsi qui: se il loro algoritmo funziona correttamente su una manciata di esempi, compresi tutti i casi angolari che possono pensare di provare, allora concludono che l'algoritmo deve essere corretto. C'è sempre uno studente che chiede: "Perché devo dimostrare il mio algoritmo corretto, se posso provarlo solo su alcuni casi di test?"
Quindi, come si fa a ingannare l'euristica "provare un mucchio di casi di prova"? Sto cercando alcuni buoni esempi per dimostrare che questa euristica non è abbastanza. In altre parole, sto cercando uno o più esempi di un algoritmo che apparentemente superficialmente potrebbe essere corretto e che fornisca la risposta giusta su tutti i piccoli input che chiunque probabilmente troverà, ma in cui l'algoritmo effettivamente non funziona Forse l'algoritmo funziona correttamente su tutti i piccoli input e fallisce solo per input di grandi dimensioni o fallisce solo per input con un modello insolito.
In particolare, sto cercando:
Un algoritmo Il difetto deve essere a livello algoritmico. Non sto cercando bug di implementazione. (Ad esempio, come minimo, l'esempio dovrebbe essere indipendente dal linguaggio e il difetto dovrebbe riguardare problemi algoritmici piuttosto che problemi di ingegneria del software o di implementazione.)
Un algoritmo che qualcuno potrebbe plausibilmente inventare. Lo pseudocodice dovrebbe apparire almeno plausibilmente corretto (ad esempio, il codice che è offuscato o ovviamente dubbioso non è un buon esempio). Punti bonus se si tratta di un algoritmo che alcuni studenti hanno escogitato durante il tentativo di risolvere un problema di compiti a casa o di esame.
Un algoritmo che avrebbe superato una ragionevole strategia di test manuale con alta probabilità. Qualcuno che prova a mano alcuni piccoli casi di test dovrebbe essere improbabile che scopra il difetto. Ad esempio, "simulare QuickCheck a mano su una dozzina di piccoli casi di test" dovrebbe essere improbabile per rivelare che l'algoritmo non è corretto.
Preferibilmente, un algoritmo deterministico. Ho visto molti studenti pensare che "provare alcuni casi di test a mano" è un modo ragionevole per verificare se un algoritmo deterministico è corretto, ma sospetto che la maggior parte degli studenti non ritenga che provare alcuni casi di test sia un buon modo per verificare probabilistici algoritmi. Per gli algoritmi probabilistici, spesso non c'è modo di dire se un determinato output è corretto; e non è possibile manovrare a sufficienza esempi per eseguire test statistici utili sulla distribuzione dell'output. Quindi, preferirei concentrarmi sugli algoritmi deterministici, poiché arrivano più chiaramente al cuore delle idee sbagliate degli studenti.
Mi piacerebbe insegnare l'importanza di dimostrare il tuo algoritmo corretto e spero di usare alcuni esempi come questo per motivare le prove di correttezza. Preferirei esempi relativamente semplici e accessibili agli studenti; esempi che richiedono macchinari pesanti o tonnellate di background matematico / algoritmico sono meno utili. Inoltre, non voglio algoritmi "innaturali"; mentre potrebbe essere facile costruire uno strano algoritmo artificiale per ingannare l'euristico, se sembra altamente innaturale o ha un'ovvia backdoor costruita solo per ingannare questo euristico, probabilmente non sarà convincente per gli studenti. Qualche buon esempio?