Para intentar probar si un algoritmo para algún problema es correcto, el punto de partida habitual es intentar ejecutar el algoritmo a mano en una serie de casos de prueba simples; pruébelo en algunos ejemplos de problemas, incluidos algunos "casos de esquina" simples ". Esta es una gran heurística: es una excelente manera de eliminar rápidamente muchos intentos incorrectos de un algoritmo y de comprender por qué el algoritmo no funciona.
Sin embargo, cuando aprenden algoritmos, algunos estudiantes se sienten tentados a detenerse allí: si su algoritmo funciona correctamente en un puñado de ejemplos, incluidos todos los casos de esquina que pueden pensar intentar, entonces concluyen que el algoritmo debe ser correcto. Siempre hay un estudiante que pregunta: "¿Por qué necesito probar que mi algoritmo es correcto, si puedo probarlo en algunos casos de prueba?"
Entonces, ¿cómo engañas a la heurística "prueba un montón de casos de prueba"? Estoy buscando algunos buenos ejemplos para demostrar que esta heurística no es suficiente. En otras palabras, estoy buscando uno o más ejemplos de un algoritmo que superficialmente parece ser correcto, y que genera la respuesta correcta en todas las entradas pequeñas que cualquiera pueda encontrar, pero donde el algoritmo realmente no funciona Tal vez el algoritmo funciona correctamente en todas las entradas pequeñas y solo falla para las entradas grandes, o solo falla para las entradas con un patrón inusual.
Específicamente, estoy buscando:
Un algoritmo La falla tiene que estar en el nivel algorítmico. No estoy buscando errores de implementación. (Por ejemplo, como mínimo, el ejemplo debe ser independiente del lenguaje y la falla debe relacionarse con preocupaciones algorítmicas en lugar de problemas de implementación o ingeniería de software).
Un algoritmo que alguien podría inventar. El pseudocódigo debería verse al menos plausiblemente correcto (por ejemplo, el código que está ofuscado u obviamente dudoso no es un buen ejemplo). Puntos de bonificación si se trata de un algoritmo que a algún alumno se le ocurrió al tratar de resolver un problema de tarea o examen.
Un algoritmo que pasaría una estrategia de prueba manual razonable con alta probabilidad. Es improbable que alguien que prueba algunos casos de prueba pequeños a mano descubra la falla. Por ejemplo, "simular QuickCheck a mano en una docena de casos de prueba pequeños" no debería revelar que el algoritmo es incorrecto.
Preferiblemente, un algoritmo determinista. He visto a muchos estudiantes pensar que "probar algunos casos de prueba a mano" es una forma razonable de verificar si un algoritmo determinista es correcto, pero sospecho que la mayoría de los estudiantes no supondría que probar algunos casos de prueba es una buena manera de verificar probabilidades algoritmos Para los algoritmos probabilísticos, a menudo no hay forma de saber si alguna salida en particular es correcta; y no puede hacer suficientes ejemplos a mano para hacer una prueba estadística útil sobre la distribución de salida. Por lo tanto, preferiría centrarme en los algoritmos deterministas, ya que llegan de manera más clara al corazón de los conceptos erróneos de los estudiantes.
Me gustaría enseñar la importancia de probar que su algoritmo es correcto, y espero utilizar algunos ejemplos como este para ayudar a motivar las pruebas de corrección. Preferiría ejemplos que sean relativamente simples y accesibles para estudiantes universitarios; Los ejemplos que requieren maquinaria pesada o un montón de antecedentes matemáticos / algorítmicos son menos útiles. Además, no quiero algoritmos que sean "antinaturales"; Si bien puede ser fácil construir algún algoritmo artificial extraño para engañar a la heurística, si se ve muy poco natural o tiene una puerta trasera obvia construida solo para engañar a esta heurística, probablemente no sea convincente para los estudiantes. ¿Algún buen ejemplo?