Чтобы попытаться проверить, является ли алгоритм для какой-либо проблемы правильным, обычная отправная точка состоит в том, чтобы попытаться запустить алгоритм вручную на нескольких простых тестовых примерах - попробуйте на нескольких примерах проблемных примеров, включая несколько простых «угловых случаев ». Это отличная эвристика: это отличный способ быстро отсеять множество неверных попыток алгоритма и понять, почему алгоритм не работает.
Тем не менее, при изучении алгоритмов у некоторых студентов возникает искушение остановиться на этом: если их алгоритм работает правильно на нескольких примерах, в том числе во всех угловых случаях, которые они могут попробовать, то они приходят к выводу, что алгоритм должен быть правильным. Всегда есть студент, который спрашивает: «Почему мне нужно доказать, что мой алгоритм правильный, если я могу просто попробовать его на нескольких тестовых примерах?»
Так как же обмануть эвристику "попробуй кучу тестов"? Я ищу несколько хороших примеров, чтобы показать, что этой эвристики недостаточно. Другими словами, я ищу один или несколько примеров алгоритма, который выглядит поверхностно, как будто он может быть правильным, и который выводит правильный ответ на все мелкие входные данные, которые могут возникнуть у любого, но где алгоритм на самом деле не работает Может быть, алгоритм просто работает правильно на всех маленьких входах и терпит неудачу только для больших входов, или терпит неудачу только для входов с необычным шаблоном.
В частности, я ищу:
Алгоритм Недостаток должен быть на алгоритмическом уровне. Я не ищу ошибки реализации. (Например, как минимум, пример должен быть независимым от языка, а недостаток должен касаться алгоритмических проблем, а не разработки программного обеспечения или реализации.)
Алгоритм, который кто-то может правдоподобно придумать. Псевдокод должен выглядеть как минимум правдоподобно правильным (например, код, который запутан или явно сомнителен, не является хорошим примером). Бонусные баллы, если это алгоритм, который на самом деле придумал какой-то студент, пытаясь решить домашнюю работу или экзаменационную задачу.
Алгоритм, который прошел бы разумную ручную стратегию тестирования с высокой вероятностью. Тот, кто пробует несколько небольших тестовых примеров вручную, вряд ли обнаружит недостаток. Например, «симуляция QuickCheck вручную на дюжине небольших тестовых случаев» вряд ли покажет, что алгоритм неверен.
Желательно, детерминированный алгоритм. Я видел, что многие студенты думают, что «пробовать некоторые тестовые примеры вручную» - это разумный способ проверить правильность детерминированного алгоритма, но я подозреваю, что большинство студентов не будут считать, что использование нескольких тестовых примеров является хорошим способом проверки вероятностных алгоритмы. Для вероятностных алгоритмов часто нет способа определить, верен ли какой-либо конкретный результат; и вы не можете провернуть достаточное количество примеров, чтобы провести какой-либо полезный статистический тест на выходное распределение. Поэтому я бы предпочел сосредоточиться на детерминистических алгоритмах, поскольку они более понятны сердцу заблуждений учащихся.
Я хотел бы рассказать о важности доказательства правильности вашего алгоритма, и я надеюсь использовать несколько подобных примеров, чтобы помочь мотивировать доказательства правильности. Я предпочел бы примеры, которые являются относительно простыми и доступными для студентов; примеры, которые требуют тяжелой техники или тонны математического / алгоритмического фона, менее полезны. Кроме того, я не хочу, чтобы алгоритмы были «неестественными»; в то время как может быть легко создать какой-то странный искусственный алгоритм, чтобы обмануть эвристику, если он выглядит крайне неестественным или имеет очевидный черный ход, созданный просто для того, чтобы обмануть эту эвристику, он, вероятно, не будет убедительным для студентов. Есть хорошие примеры?