Наука и искусство алгоритмизации
Составление алгоритмов — это работа творческая. Нет общего способа, пользуясь которыми мы могли бы составлять любые необходимые алгоритмы. Все, начиная с выбора языков и кончая составлением алгоритма, зависит от вкусов и творческих способностей человека.
Могут сказать: но ведь есть простейшие случаи, в которых алгоритмы можно составлять по определенной схеме. В чем же тут заключается творчество?
Давайте посмотрим, что это за случаи. Это, пожалуй, те случаи, в которых алгоритм решения уже получен кем-нибудь другим. Например, существует метод Эйлера для численного интегрирования дифференциальных уравнений. Нетрудно для конкретного дифференциального уравнения составить алгоритм его решения методом Эйлера. Но метод Эйлера как раз и представляет собой сделанное в общем виде описание этого алгоритма! В § 2 гл. 2 мыуже говорили о том, как получают алгоритмы. Теперь мы xoтим\ снова вернуться к этому вопросу, имея значительно 6oльшее вооружение, для того чтобы к нему подступиться. Мы можем изложить даже некоторую теорию алгоритмизации.
Если перед нами стоит проблема разработки некоторого алгоритма, то первым шагом ее решения можно считать исследование вопроса: возможен или невозможен искомый алгоритм. В некоторых случаях удается установить невозможность алгоритма. Это, хотя и отрицательное, но все же решение стоящей задачи.
В других случаях удается доказать возможность алгоритма. Это еще не означает, что алгоритм найден, но все же является некоторым продвижением вперед. Доказательство существования алгоритма обычно заключается в том, что описывают процесс, с помощью которого его можно построить. Получаемый при этом алгоритм может быть реально осуществимым либо из-за необычайно большого числа предписываемых им операций, либо из-за того что получаемые в процессе его выполнения промежуточные результаты содержат огромные количества символов (не хватит никаких запоминающих устройств для их размещения). Такой алгоритм нельзя считать решением заданы алгоритмизации. Все же, если даже неэффективный алгоритм реально составлен в виде некоторого предложения формального языка, это нас обнадеживает. Если алгоритм возможен, то среди ему эквивалентных иногда найдется и пригодный для практических целей.
Конечно, может быть, мы не сумеем доказать ни возможность, ни невозможность алгоритма. Что делать в этом случае — неизвестно. Автор полагает, что нужно жать исследования.
Следующим этапом работы является построение хотя бы одного, хотя бы какого-нибудь алгоритма. И вот здесь мы должны использовать опыт построения алгоритмов, накопленный человечеством. Этот опыт довольно значителен. Есть целая математическая дисциплина, называемая вычислительной математикой, предметом которой является построение различных алгоритмов для решения различных задач. Эта наука охватывает широкий круг вопросов, связанных с построением вычислительных алгоритмов. Учитывая особенности вычислительных задач, она предлагает большое число методов как точного, так и приближенного решения вычислительных задач, и учит оценивать допускаемые при расчетах погрешности.
Хотя автор и сказал: «Построение хотя бы какого-нибудь алгоритма», но, конечно, нужно стремиться получить сразу «хороший» алгоритм, если это удается. Если же ни один из известных приемов не позволит получить «хороший» алгоритм, возникает вопрос: нельзя ли, отправляясь от «плохого», улучшить его настолько, чтобы он стал приемлемым?
В настоящее время уже начата новая глава теории алгоритмов. Алгоритмы, предназначенные для решения задач, можно подвергать некоторым преобразованиям, значительно их изменяя, однако так, чтобы они продолжали соответствовать задаче, для которой составлены.
Некоторые преобразования связаны с видоизменением алгоритмического и операндного языков, другие преобразования оставляют нас в рамках прежних языков[29]. К сожалению, метода направленных преобразований нет. Если мы хотим с помощью равносильных преобразований улучшить алгоритм, то должны при этом руководствоваться интуицией, а в ряде случаев действовать наудачу. Преобразовав алгоритм, мы проверяем: стал ли он лучше? Смотрим, нельзя ли его еще улучшить?
При этом мы встречаемся с одной трудностью. Слова «лучше», «хуже», «хороший», «плохой» применительно к алгоритмам не имеют точного смысла. Когда алгоритм очень «плох», нам это ясно. Когда он очень «хорош», мы тоже каким-то шестым, а может быть, и седьмым чувством это воспринимаем. Но в «средних» случаях наше седьмое чувство молчит.
Очень грубые критерии для оценки качества алгоритма мы имеем. Можно считать, что алгоритм плох, если при его выполнении требуется такой объем запоминающих устройств, каким мы не располагаем. Этот алгоритм настолько «плох», что с его помощью нельзя решать задачи. Но и здесь, конечно, речь идет не вообще о необходимом объеме запоминающих устройств, а лишь об объеме, необходимом для тех исходных данных, которые могут встречаться на практике.
Итак, прежде всего нужно выделить некоторое множество исходных данных и только для исходных данных, взятых из него, оценивать потребный объем запоминающих устройств.
Если допустимый максимум объема обозначить V*, то коль скоро алгоритм таков, что V ≤ V*, где V — потребный объем, то стремиться к дальнейшему уменьшению потребного объема уже незачем. Этот критерий перестает действовать.
Теперь начинает действовать новый критерий: потребное время. Для оценки времени нужно учесть физические характеристики исполнителя. Очень грубо можно оценивать время, если известно «среднее быстродействие» исполнителя. Каждую операцию при каждом значении операнда исполнитель производит за определенное время. Но таких точных сведений об исполнителе мы обычно не имеем. Нам бывает известно некоторое среднее быстродействие, подсчитанное в предположении, что каждый вид операций и каждый вид исходного для нее данного в процессе выполнения алгоритма встречается с определенной известной вероятностью. За неимением других характеристик приходится пользоваться этой очень неточной характеристикой исполнителя. Определяя количество последовательно выполняемых операций и умножая их число на среднее быстродействие, получаем условное время выполнения алгоритма.
Сделаем допущение, что условное время является действительным временем выполнения. И тогда из двух алгоритмов, удовлетворяющих условию V ≤ V*, лучше тот, для которого время выполнения меньше. Сам метод оценки неточен, и потому стремиться к получению наилучшего алгоритма — дело бессмысленное. Такой «наилучший» алгоритм может быть хуже многих других. Обычно нам известно максимальное допустимое время Т и, коль скоро мы нашли алгоритм, время выполнения которого удовлетворяет условию t<T, проблема считается решенной.
Мы видим, что уже зарождается теория сложности алгоритмов. Нужно отметить и чисто абстрактное направление в этой теории. Некоторые ученые мерой сложности алгоритма считают сложность наиболее простой из эквивалентных ему машин Тьюринга. Мы на этих интересных вопросах останавливаться не будем[30].
ЗАКЛЮЧЕНИЕ
Может ли машина мыслить?