"Информатика (базовый и углублённый уровень)", Гейн А.Г., Сенокосов А.И.
Алгоритм считают применимым, если на всех входных данных, для которых он предназначен, он выполняет допустимые действия, заканчивает работу и выдаёт результат, отвечающий условию задачи. Успешных запусков на нескольких примерах для доказательства недостаточно: нужно обосновать работу алгоритма в общем случае. Для этого проверяют ограничения на входные данные, правильность промежуточных шагов и результата, а в циклах — сохранение нужного свойства и конечность выполнения.
Текст подготовлен нейронной сетью по теме параграфа и не заменяет учебник — важные факты и формулировки сверяйте с ним.
Алгоритм — точное описание последовательности действий, которая приводит к решению задачи. Его выполнение зависит от исходных данных: один и тот же алгоритм может получать разные входы и выдавать разные результаты. Поэтому, описывая алгоритм, указывают, какие данные он принимает. Это помогает понять, для каких случаев его работу нужно обосновать.
Область применимости алгоритма — множество входных данных, для которых он гарантированно решает поставленную задачу. Например, алгоритм, который делит одно число на другое, может быть рассчитан только на ненулевой делитель. Указание области применимости отделяет допустимые случаи от тех, для которых обещание алгоритма не действует. Это нужно, чтобы доказательство относилось именно к тем данным, на которых алгоритм должен работать.
Корректность алгоритма — соответствие полученного результата условию задачи для всех допустимых входных данных. Речь идёт не о том, что ответ выглядит правдоподобно, а о том, что он действительно решает поставленную задачу. Корректность проверяют, связывая действия алгоритма с требуемым результатом. Это позволяет обосновать правильность не только одного запуска, но и всего алгоритма.
Завершаемость алгоритма — свойство, при котором выполнение заканчивается за конечное число шагов. Даже если каждое действие допустимо, алгоритм может повторять действия бесконечно. Поэтому завершение рассматривают отдельно от правильности результата. Без него алгоритм может никогда не выдать ответ.
Проверка нескольких примеров показывает только, что алгоритм сработал на этих конкретных входах. Среди допустимых данных могут быть особые случаи, которые проверка не затронула, например минимальное значение или повторяющиеся элементы. Поэтому примеры полезны для поиска ошибок, но не гарантируют общей правильности. В доказательстве нужно объяснить, почему алгоритм работает для любого входа из заданной области.
Область применимости задаётся условиями задачи и ограничениями, при которых алгоритм разработан. Если алгоритм ожидает положительные числа, отрицательное значение может сделать его действия бессмысленными или нарушить обоснование. Сначала выясняют, какие входы разрешены, и только затем доказывают работу на них. Так условия задачи становятся частью доказательства, а не просто описанием примера.
Корректность обосновывают, прослеживая смысл каждого действия: оно должно быть допустимым и сохранять нужные свойства данных. Затем показывают, что после последнего действия полученное значение удовлетворяет условию задачи. Для цикла удобно доказать инвариант — свойство, которое верно до начала повторений и сохраняется после каждого шага. Тогда ход вычислений связан с тем, что требуется получить.
Завершение требует отдельного доказательства, потому что правильные промежуточные шаги сами по себе не ограничивают их количество. Например, цикл может каждый раз выполнять допустимое действие, но не приближаться к условию остановки. Чтобы исключить бесконечное выполнение, находят величину, которая строго изменяется в нужную сторону и не может изменяться так бесконечно. В простом случае это положительное целое число, которое уменьшается на каждом шаге.
Разбирая циклический алгоритм, сначала выбирают инвариант, связанный с задачей, и проверяют, что он верен до первой итерации. Затем доказывают, что очередной шаг сохраняет это свойство. Отдельно устанавливают, что цикл остановится, например потому, что убывающая положительная величина рано или поздно достигнет граничного значения. После остановки используют инвариант вместе с условием выхода, чтобы обосновать ответ.
Таблица помогает последовательно проверить основные стороны работы алгоритма. Сначала сопоставьте входы с ограничениями задачи, затем разберите действия и результат. В последнюю очередь задайте вопрос о том, почему выполнение обязательно остановится.
| Проверяемый аспект | Что нужно установить | Вопрос для проверки |
|---|---|---|
| Допустимость исходных данных | Входные данные удовлетворяют ограничениям задачи | Для каких данных алгоритм предназначен? |
| Корректность действий | Каждый шаг допустим и сохраняет необходимые свойства | Почему можно выполнить следующий шаг? |
| Правильность результата | Полученный результат решает исходную задачу | Почему итог удовлетворяет условию? |
| Завершение | Алгоритм заканчивает работу за конечное число шагов | Почему выполнение не может продолжаться бесконечно? |
Условие. Для алгоритма вычисления суммы двух целых чисел укажите допустимые входные данные и объясните, почему результат верен. Важно разделить ограничения на вход и доказательство ответа: это разные части проверки. Сложение определено для любых двух целых чисел, поэтому дополнительных ограничений на них нет.
Ответ. Допустимы любые пары целых чисел. Алгоритм выдаёт их сумму, а значит, результат отвечает условию задачи; поскольку выполнено одно действие, алгоритм также заканчивает работу.
Условие. Даны два положительных целых числа. Алгоритм вычитает меньшее из большего, пока числа не станут равны. Нужно доказать, что общее значение равно наибольшему общему делителю (НОД) исходных чисел и что алгоритм завершится. Здесь надо отдельно обосновать сохранение ответа и остановку процесса.
Ответ. На положительных целых входах алгоритм сохраняет НОД и обязательно останавливается, когда числа равны. Полученное общее число является наибольшим общим делителем исходной пары.
Условие. Алгоритм последовательно просматривает элементы непустого массива и хранит текущий максимум. Нужно доказать, что после первых k элементов сохранено наибольшее из них, а после всего массива найден ответ. Здесь полезно связать правильность каждого шага с числом уже просмотренных элементов.
Ответ. Алгоритм находит максимальный элемент непустого массива: инвариант обосновывает правильность результата, а конечное число элементов — завершение.
Для рассуждений о применимости нужны понятия алгоритма, входных данных, результата и условия задачи: они помогают задать, что именно требуется обосновать. Если забыть о допустимых входах, нельзя точно сформулировать область, на которой действует доказательство. Проверка корректности и завершения пригодится при разработке программ, анализе циклов и поиске ошибок в алгоритмах. Инвариант позволяет объяснить, почему повторяющиеся действия ведут к нужному результату, а не просто выполняются по очереди.
Чем применимость алгоритма отличается от его корректности?
Применимость рассматривают относительно заданной области входных данных и включает обоснование работы алгоритма на всех данных из этой области. Корректность — часть такого обоснования: она означает, что результат соответствует условию задачи.
Почему нельзя доказать применимость, проверив алгоритм на нескольких примерах?
Конечное число примеров не охватывает все возможные допустимые входные данные. Даже если алгоритм сработал в проверенных случаях, на другом входе он может нарушить условие или не завершиться.
Зачем отдельно доказывать, что алгоритм завершится?
Алгоритм может выполнять правильные действия, но повторять их бесконечно и так и не выдать ответ. Доказательство завершения показывает, что выполнение закончится за конечное число шагов.
Что такое инвариант цикла и как он помогает доказать корректность?
Инвариант цикла — свойство данных, которое верно до начала цикла и сохраняется после каждой итерации. Если оно связывает промежуточные данные с условием задачи, то после завершения цикла помогает обосновать правильность результата.
Что делать, если входные данные не удовлетворяют ограничениям алгоритма?
Такие данные не входят в область применимости, поэтому гарантировать для них правильную работу алгоритма нельзя. Нужно проверить ограничения до запуска либо изменить алгоритм так, чтобы он обрабатывал эти данные.
§ 48. Как доказывают применимость алгоритма