Pour essayer de vérifier si un algorithme est correct pour un problème donné, le point de départ habituel est d'essayer de l'exécuter à la main sur un certain nombre de cas de test simples. Essayez-le sur quelques exemples de problèmes, y compris quelques "cas simples". ". C'est une excellente heuristique: c'est un excellent moyen d'éliminer rapidement de nombreuses tentatives incorrectes d'algorithme et de comprendre pourquoi cet algorithme ne fonctionne pas.
Cependant, lors de l’apprentissage des algorithmes, certains étudiants sont tentés de s’arrêter là: si leur algorithme fonctionne correctement avec quelques exemples, y compris tous les cas difficiles qu’ils peuvent penser, ils concluent que l’algorithme doit être correct. Il y a toujours un étudiant qui demande: "Pourquoi dois-je prouver que mon algorithme est correct, si je peux simplement l'essayer sur quelques cas de test?"
Alors, comment vous tromper l'heuristique «essayez un tas de cas de test»? Je cherche de bons exemples pour montrer que cette heuristique ne suffit pas. En d’autres termes, je cherche un ou plusieurs exemples d’algorithmes qui, superficiellement, semblent pouvoir être corrects et qui fournissent la bonne réponse pour toutes les petites entrées susceptibles d’être fournies par quiconque, mais dont ne fonctionne pas. Peut-être que l'algorithme fonctionne correctement sur toutes les petites entrées et échoue uniquement pour les grandes entrées, ou uniquement pour les entrées avec un motif inhabituel.
Plus précisément, je recherche:
Un algorithme. La faille doit être au niveau algorithmique. Je ne cherche pas de bogues de mise en œuvre. (Par exemple, au minimum, l'exemple devrait être indépendant de la langue et la faille devrait concerner des problèmes algorithmiques plutôt que des problèmes d'ingénierie logicielle ou de mise en œuvre.)
Un algorithme que quelqu'un pourrait plausiblement proposer. Le pseudo-code doit avoir au moins une apparence plausible (par exemple, un code obscurci ou douteux n’est pas un bon exemple). Des points bonus s’il s’agit d’un algorithme créé par un étudiant lorsqu’il tente de résoudre un problème de devoirs ou d’examen.
Un algorithme qui passerait avec une stratégie de test manuel raisonnable avec une probabilité élevée. Il est peu probable que quelqu'un qui teste quelques petits cas de test à la main découvre la faille. Par exemple, "simuler QuickCheck manuellement à la main sur une douzaine de petits cas de test" ne devrait probablement pas révéler que l'algorithme est incorrect.
De préférence, un algorithme déterministe. J'ai vu beaucoup d'étudiants penser qu'essayer quelques cas de test à la main est un moyen raisonnable de vérifier si un algorithme déterministe est correct, mais je suppose que la plupart des étudiants ne présumeraient pas qu'essayer quelques cas de test est un bon moyen de vérifier des méthodes probabilistes. algorithmes. Pour les algorithmes probabilistes, il est souvent impossible de déterminer si une sortie donnée est correcte. et vous ne pouvez pas donner assez d'exemples pour effectuer un test statistique utile sur la distribution de la sortie. Je préférerais donc me concentrer sur les algorithmes déterministes, car ils vont plus clairement au cœur des idées fausses des étudiants.
J'aimerais enseigner l'importance de prouver que votre algorithme est correct, et j'espère utiliser quelques exemples comme celui-ci pour aider à motiver les preuves de l'exactitude. Je préférerais des exemples relativement simples et accessibles aux étudiants de premier cycle; Les exemples qui nécessitent des machines lourdes ou une tonne de connaissances mathématiques / algorithmiques sont moins utiles. En outre, je ne veux pas d’algorithmes «non naturels»; S'il est peut-être facile de construire un algorithme artificiel étrange pour tromper l'heuristique, s'il semble extrêmement artificiel ou si sa porte dérobée est construite simplement pour tromper cette heuristique, il ne sera probablement pas convaincant pour les étudiants. Des bons exemples?