Para tentar testar se um algoritmo para algum problema está correto, o ponto de partida usual é tentar executar o algoritmo manualmente em vários casos de teste simples - tente em alguns exemplos de instâncias de problemas, incluindo alguns casos de canto "simples" " Essa é uma ótima heurística: é uma ótima maneira de eliminar rapidamente muitas tentativas incorretas de um algoritmo e entender melhor por que o algoritmo não funciona.
No entanto, ao aprender algoritmos, alguns alunos ficam tentados a parar por aí: se seu algoritmo funciona corretamente em alguns exemplos, incluindo todos os casos de canto que eles podem pensar em tentar, então concluem que o algoritmo deve estar correto. Sempre há um aluno que pergunta: "Por que preciso provar meu algoritmo correto, se posso experimentá-lo em alguns casos de teste?"
Então, como você engana a heurística "experimente vários casos de teste"? Estou procurando alguns bons exemplos para mostrar que essa heurística não é suficiente. Em outras palavras, estou procurando um ou mais exemplos de um algoritmo que superficialmente pareça estar correto, e que dê a resposta certa em todas as pequenas entradas que qualquer pessoa provavelmente encontrará, mas onde o algoritmo realmente não funciona Talvez o algoritmo funcione corretamente em todas as entradas pequenas e falhe apenas para entradas grandes ou apenas para entradas com um padrão incomum.
Especificamente, estou procurando:
Um algoritmo A falha deve estar no nível algorítmico. Não estou procurando por erros de implementação. (Por exemplo, no mínimo, o exemplo deve ser independente da linguagem e a falha deve estar relacionada a preocupações algorítmicas, em vez de questões de engenharia ou implementação de software.)
Um algoritmo que alguém pode apresentar de maneira plausível. O pseudocódigo deve parecer pelo menos plausivelmente correto (por exemplo, código ofuscado ou obviamente dúbio não é um bom exemplo). Pontos de bônus se for um algoritmo que algum aluno realmente apresentou ao tentar resolver um problema de lição de casa ou de exame.
Um algoritmo que passaria em uma estratégia razoável de teste manual com alta probabilidade. É improvável que alguém que tente manualmente alguns pequenos casos de teste descubra a falha. Por exemplo, "simular o QuickCheck manualmente em uma dúzia de pequenos casos de teste" não deve revelar que o algoritmo está incorreto.
De preferência, um algoritmo determinístico. Já vi muitos estudantes pensarem que "experimentar alguns casos de teste manualmente" é uma maneira razoável de verificar se um algoritmo determinístico está correto, mas suspeito que muitos estudantes não considerariam que tentar alguns casos de teste é uma boa maneira de verificar probabilística. algoritmos. Para algoritmos probabilísticos, geralmente não há como saber se alguma saída específica está correta; e você não pode manobrar com exemplos suficientes para fazer qualquer teste estatístico útil na distribuição de saída. Portanto, eu preferiria me concentrar em algoritmos determinísticos, pois eles chegam mais claramente ao coração dos conceitos errados dos alunos.
Gostaria de ensinar a importância de provar seu algoritmo correto, e espero usar alguns exemplos como esse para ajudar a motivar provas de correção. Eu preferiria exemplos que sejam relativamente simples e acessíveis aos estudantes de graduação; exemplos que exigem maquinaria pesada ou uma tonelada de conhecimentos matemáticos / algorítmicos são menos úteis. Além disso, não quero algoritmos "não naturais"; embora possa ser fácil construir algum algoritmo artificial estranho para enganar a heurística, se parecer altamente artificial ou se houver um backdoor óbvio construído apenas para enganar essa heurística, provavelmente não será convincente para os alunos. Algum bom exemplo?