Набор Алгоритмов

Статья посвящена тому, как сравнивать алгоритмы. Статья позволит определять математическую сложность алгоритмов. Возможно это не поможет сделать Ваш алгоритм оптимальным, т.к. он уже оптимальный, но даст Вам возможность определить узкие места, что позволит: более правильно разбить алгоритм по реальной, конечной (для Вас) электронике; изменить тип входных данных; изменить человеко-машинный интерфейс программы, и т.п.

Алгоритмы - Сложность алгоритмов. Введение

1. Основы оценки математической сложности алгоритмов.

Математическая сложность алгоритма равна сумме весов всех операций процессора выполняемых от начала алгоритма до его отработки.

Пусть в алгоритме используются следующие операции с указанными весами, для примера.

П.п.Вес операцииОперация
11+
21-
31Вызов
41/
51*
61Присвоение, =
71<
81>
91==
101!=
111<=
121>=
131Возврат
141Чтение переменной
15В зависимости от тела функцииВыполнение функции
16В зависимости от цикла (сложность тела цикла * количество повторений)Выполнение цикла
17И т.п.И т.д.

Сам алгоритм таков:

function int main(){
    return f1();
}

function int f1() {
    int result = 0;
    for(int i = 1; i <= 5; i = i + 1) {
        result = result + 2;
    }
    return result;
}

Оценим сложность вышеприведённой функции main:

П.п.Вес операцииОперация
11Возврат
2В зависимости от тела функцииВыполнение функции

Оценим сложность выполнения функции f1:

П.п.Вес операцииОперацияСтрока
11Присвоениеint result = 0;
21Присвоениеfor(int i = 1; i <= 5; i = i + 1) {
31Чтение переменной ifor(int i = 1; i <= 5; i = i + 1) {
41<=for(int i = 1; i <= 5; i = i + 1) {
51Чтение переменной resultresult = result + 2;
61+result = result + 2;
71Присвоение, =result = result + 2;
81Чтение переменной ii = i + 1
91+i = i + 1
101Присвоение, =i = i + 1
11-3424Повторение операций подпунктов [3, 4, 5, 6, 7, 8, 9, 10] 4 раза.
351Чтение переменной ifor(int i = 1; i <= 5; i = i + 1) {
361<=for(int i = 1; i <= 5; i = i + 1) {
371Возвратreturn result;

Итого сложность выполнения вышеописанного метода main: 1 + 37 = 38.

Оптимизируем алгоритм main:

function int main(){
    return f1();
}

function int f1() {
    return 2*5;
}

Или:

function int main(){
    return 10;
}

Как видно из оптимизации сложность оптимизированного алгоритма равна 1 - Т.е. изначально алгоритм был не правильный. - Выбирайте за что платить, за количество строк в алгоритме или за информативность одной строки. Выберите платить за "и": и за то, и за то (за количество информативных строк). Но для этого нужны исследования, а не программирование на время за человекочас, поэтому лучше выбирать среднее, но в будущем Вы обязательно его оптимизируете.

2. Оценка алгоритмов на реальной электронике.

На реальной электронике вес выполнения одной операции может быть различен, не равен всегда единице, т.к. оперативная память медленнее регистров процессора, жёсткий диск медленнее оперативной памяти, сеть медленнее жёсткого диска. Поэтому проверяйте среднее время выполнения на реальной элетронике.

Для проведения тестов всего лишь нужно запустить тест на время выполнения много раз, получив статистику, Вы можете определить среднее время выполнения - Это делает алгоритмы сравнимыми тоже.

Для проведения этих тестов можно использовать разницу времени входа в метод и выхода. Или среду тестирования.

3. Основные аксиомы.

В данном разделе полученные опытом разработки напутствия для концентрирования Вашего внимания на аспектах разработки алгоритмов.

3.1. Аксиома 1: Равенство.

Это оптимальный алгоритм?

Аксиома 1: Равенство: Если разделить на объекты, то есть одинаковый по сложности путь решения математической задачи на процессоре. Т.е. если одинаковое дано, и одинаковый тип входных данных, и дальнейшее утверждения верно для одного процессора - в этом случае алгоритмы равны и не могут быть разными.

Эта аксиома верна при логическом написании кода программы. Т.е. если Вы не делаете 2-2, чтобы объявить нуль, но и тут может помочь оптимизатор. Есть способ оптимизации по реальной электронике: изменить тип данных (разбить хранение одних данных на одном компьютере, другой категории на другом), увеличить, в любом случае, мощность серверов, изменить интерфейс программы и т.п.

3.2. Аксиома 2: Прямое действие управляющего глагола.

Это та программа?

Аксиома 2: Прямое действие управляющего глагола: Если Ваша программа делает то, что обещала, то не занимайтесь оптимизацией за миллисекунды, оптимизация начинается за существенное время. Если программа, допустим, распознаёт текст на персональном компьютере, а программа работает быстрее только если увеличить вычислительную мощность, то смело ставьте полосу ожидания.

Это значит, что приоритетнее ввод нового функционала в программу, нежели борьба за миллисекунды. Но это не значит, что, как пример, Вы не будете менять интерфейс программы, который повлияет на скорость обработки данных на многоядерных системах.

3.3. Аксиома 3: Фрагментация.

Это быстрая программа?

Аксиома 3: Фрагментация: Это разбиение программы и данных на независимые блоки. Не путайте с кластеризацией, где есть общая шина.

Это может быть, к примеру, разделение пользовательского интерфейса по серверам: для интернета магазина, одежда храниться на одном сервере, хозтовары - на другом, но в целом это один домен сервера.

3.4. Аксиома 4: Передача результата.

А как? Это реальная электроника!

Аксиома 4: Передача результата: К примеру, с планеты на планету передают не весь госреестр, а только результат с подписью, для принятия сложных и быстрых решений.

Этот результат со всех планет обрабатывается общей шиной, но фрагментирован по планетам.

4. Заключение и пожелания.

Пишите свои программы, как понимаете, главное выполнение прямого результата действия программы в установленные (допустимые) сроки. В конце, как получите прямой результат, вы можете оптимизировать программу. Но в этом направлении главное не забывать ознакомиться с предметной областью программы.