чем определяется сложность по

Чем определяется сложность по

Классификацию систем можно осуществить по разным критериям. Ее часто жестко невозможно проводить и она зависит от цели и ресурсов. Приведем основные способы классификации (возможны и другие критерии классификации систем).

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

Пример. Рассмотрим экологическую систему «Озеро». Это открытая, естественного происхождения система, переменные которой можно описывать смешанным образом (количественно и качественно, в частности, температура водоема — количественно описываемая характеристика), структуру обитателей озера можно описать и качественно, и количественно, а красоту озера можно описать качественно. По типу описания закона функционирования системы, эту систему можно отнести к не параметризованным в целом, хотя возможно выделение подсистем различного типа, в частности, различного описания подсистемы «Водоросли», «Рыбы», «Впадающий ручей», »Вытекающий ручей», «Дно», «Берег» и др. Система «Компьютер» — открытая, искусственного происхождения, смешанного описания, параметризованная, управляемая извне (программно). Система «Логический диск» — открытая, виртуальная, количественного описания, типа «Белый ящик» (при этом содержимое диска мы в эту систему не включаем!), смешанного управления. Систем «Фирма» — открытая, смешанного происхождения (организационная) и описания, управляемая изнутри (адаптируемая, в частности, система).

Система называется большой, если ее исследование или моделирование затруднено из-за большой размерности, т.е. множество состояний системы S имеет большую размерность. Какую же размерность нужно считать большой? Об этом мы можем судить только для конкретной проблемы (системы), конкретной цели исследуемой проблемы и конкретных ресурсов.

Большая система сводится к системе меньшей размерности использованием более мощных вычислительных средств (или ресурсов) либо разбиением задачи на ряд задач меньшей размерности (если это возможно).

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

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

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

Сложность этих систем обусловлена их сложным поведением. Сложность системы зависит от принятого уровня описания или изучения системы-макроскопического или микроскопического.

Сложность системы может быть внешней и внутренней.

Внутренняя сложность определяется сложностью множества внутренних состояний, потенциально оцениваемых по проявлениям системы, сложностью управления в системе.

Внешняя сложность определяется сложностью взаимоотношений с окружающей средой, сложностью управления системой потенциально оцениваемых по обратным связям системы и среды.

Сложные системы бывают:

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

чем определяется сложность по. Смотреть фото чем определяется сложность по. Смотреть картинку чем определяется сложность по. Картинка про чем определяется сложность по. Фото чем определяется сложность по

Заполненность матрицы А (ее структура, связность) будет отражать сложность описываемой системы. Если, например, матрица А — верхнетреугольная матрица (элемент, расположенный на пересечении i-ой строки и j-го столбца всегда равен 0 при i > j), то независимо от n (размерности системы) она легко исследуется на разрешимость. Для этого достаточно выполнить обратный ход метода Гаусса. Если же матрица А — общего вида (не является ни симметричной, ни ленточной, ни разреженной и т.д.), то систему сложнее исследовать (так как при этом необходимо выполнить более вычислительно и динамически сложную процедуру прямого хода метода Гаусса). Следовательно, система будет обладать структурной сложностью (которая уже может повлечь за собой и вычислительную сложность, например, при нахождении решения). Если число n достаточно в елико, то неразрешимость задачи хранения матрицы А верхнетреугольного вида в оперативной памяти компьютера может стать причиной вычислительной и динамической сложности исходной задачи. Попытка использовать эти данные путем считывания с диска приведет к многократному увеличению времени счета (увеличит динамическую сложность — добавятся факторы работы с диском).

Пример. Пусть имеется динамическая система, поведение которой описывается задачей Коши вида:

Эта задача имеет решение:

Отсюда видно, что y(t) при k = 10 изменяется на порядок быстрее, чем y(t) при k = 1 и динамику системы сложнее будет отслеживать: более точное предсказание для t → 0 и малых c связано с дополнительными затратами на вычисления т.е. алгоритмически, информационно, динамически и структурно «не очень сложная система» (при a, k ≠ 0) может стать вычислительно и, возможно, эволюционно сложной (при t → 0), а при больших t (t → ∞) и непредсказуемой. Например, при больших t значения накапливаемых погрешностей вычислений решения могут перекрыть значения самого решения. Если при этом задавать нулевые начальные данные а ≠ 0, то система может перестать быть, например, информационно несложной, особенно, если а трудно априорно определить.

Пример. Упрощение технических средств для работы в сетях, например, научные достижения, позволяющие подключать компьютер непосредственно к сети, «к розетке электрической сети» наблюдается наряду с усложнением самих сетей, например, увеличением количества абонентов и информационных потоков в Интернет. Наряду с усложнением самой сети Интернет упрощаются (для пользователя!) средства доступа к ней, увеличиваются ее вычислительные возможности.

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

Само понятие сложности системы не является чем-то универсальным, неименным и может меняться динамически, от состояния к состоянию. При этом и слабые связи, взаимоотношения подсистем могут повышать сложность системы.

Пример. Рассмотрим процедуру деления единичного отрезка [0; 1] с последующим выкидыванием среднего из трех отрезков и достраиванием на выкинутом отрезке равностороннего треугольника (рис.); эту процедуру будем повторять каждый раз вновь к каждому из остающихся после выкидывания отрезков. Этот процесс является структурно простым, но динамически является сложным, более того образуется динамически интересная и трудно прослеживаемая картина системы, становящейся «все больше и больше, все сложнее и сложнее». Такого рода структуры называются фракталами или фрактальными структурами (фрактал — от fraction — дробь и fracture — излом т.е. изломанный объект с дробной размерностью). Его отличительная черта — самоподобие, т.е. сколь угодно малая часть фрактала по своей структуре подобна целому, как ветка — дереву.

чем определяется сложность по. Смотреть фото чем определяется сложность по. Смотреть картинку чем определяется сложность по. Картинка про чем определяется сложность по. Фото чем определяется сложность по

Рис. Фрактальный объект (кривая Коха)

Уменьшив сложность системы можно часто увеличить ее информативность, исследуемость.

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

Система называется устойчивой, если она сохраняет тенденцию стремления к тому состоянию, которая наиболее соответствует целям системы, целям сохранения качества без изменения структуры или не приводящим к сильным изменениям структуры системы на некотором заданном множестве ресурсов (например, на временном интервале). Понятие «сильное изменение» каждый раз должно быть конкретизировано, детерминировано.

Пример. Рассмотрим маятник, подвешенный в некоторой точке и отклоняемый от положения равновесия на угол 0 ≤ φ ≤ π. Маятник будет структурно, вычислительно, алгоритмически и информационно устойчив в любой точке, а при φ = 0 (состояние покоя маятника) — устойчив и динамически, эволюционно (самоорганизационные процессы в маятнике на микроуровне мы не учитываем). При отклонении от устойчивого состояния равновесия маятник, самоорганизуясь, стремится к равновесию. При φ = π маятник переходит в динамически неустойчивое состояние. Если же рассматривать лед (как систему), то при температуре таяния эта система структурно неустойчива. Рынок — при неустойчивом спросе (предложении) неустойчив структурно, эволюционно.

Система называется связной, если любые две подсистемы обмениваются ресурсом, т.е. между ними есть некоторые ресурсоориентированные отношения, связи.

Источник

Оценка сложности алгоритмов

Введение

Для любого программиста важно знать основы теории алгоритмов, так как именно эта наука изучает общие характеристики алгоритмов и формальные модели их представления. Ещё с уроков информатики нас учат составлять блок-схемы, что, в последствии, помогает при написании более сложных задач, чем в школе. Также не секрет, что практически всегда существует несколько способов решения той или иной задачи: одни предполагают затратить много времени, другие ресурсов, а третьи помогают лишь приближённо найти решение.

Всегда следует искать оптимум в соответствии с поставленной задачей, в частности, при разработке алгоритмов решения класса задач.
Важно также оценивать, как будет вести себя алгоритм при начальных значениях разного объёма и количества, какие ресурсы ему потребуются и сколько времени уйдёт на вывод конечного результата.
Этим занимается раздел теории алгоритмов – теория асимптотического анализа алгоритмов.

Предлагаю в этой статье описать основные критерии оценки и привести пример оценки простейшего алгоритма. На Хабрахабре уже есть статья про методы оценки алгоритмов, но она ориентирована, в основном, на учащихся лицеев. Данную публикацию можно считать углублением той статьи.

Определения

Основным показателем сложности алгоритма является время, необходимое для решения задачи и объём требуемой памяти.
Также при анализе сложности для класса задач определяется некоторое число, характеризующее некоторый объём данных – размер входа.
Итак, можем сделать вывод, что сложность алгоритма – функция размера входа.
Сложность алгоритма может быть различной при одном и том же размере входа, но различных входных данных.

Существуют понятия сложности в худшем, среднем или лучшем случае. Обычно, оценивают сложность в худшем случае.

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

Порядок роста сложности алгоритмов

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

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

Виды асимптотических оценок

O – оценка для худшего случая

Рассмотрим сложность f(n) > 0, функцию того же порядка g(n) > 0, размер входа n > 0.
Если f(n) = O(g(n)) и существуют константы c > 0, n0 > 0, то
0 n0.

чем определяется сложность по. Смотреть фото чем определяется сложность по. Смотреть картинку чем определяется сложность по. Картинка про чем определяется сложность по. Фото чем определяется сложность по

Функция g(n) в данном случае асимптотически-точная оценка f(n). Если f(n) – функция сложности алгоритма, то порядок сложности определяется как f(n) – O(g(n)).

Данное выражение определяет класс функций, которые растут не быстрее, чем g(n) с точностью до константного множителя.

Примеры асимптотических функций
f(n)g(n)
2n 2 + 7n — 3n 2
98n*ln(n)n*ln(n)
5n + 2n
81
Ω – оценка для лучшего случая

Критерии оценки сложности алгоритмов

Равномерный весовой критерий (РВК) предполагает, что каждый шаг алгоритма выполняется за одну единицу времени, а ячейка памяти за одну единицу объёма (с точностью до константы).
Логарифмический весовой критерий (ЛВК) учитывает размер операнда, который обрабатывается той или иной операцией и значения, хранимого в ячейке памяти.
чем определяется сложность по. Смотреть фото чем определяется сложность по. Смотреть картинку чем определяется сложность по. Картинка про чем определяется сложность по. Фото чем определяется сложность по

Временная сложность при ЛВК определяется значением l(Op), где Op – величина операнда.
Ёмкостная сложность при ЛВК определяется значением l(M), где M – величина ячейки памяти.

Пример оценки сложности при вычислении факториала

Необходимо проанализировать сложность алгоритма вычисление факториала. Для этого напишем на псевдокоде языка С данную задачу:

Временная сложность при равномерном весовом критерии

Достаточно просто определить, что размер входа данной задачи – n.
Количество шагов – (n — 1).

Таким образом, временная сложность при РВК равна O(n).

Временная сложность при логарифмическом весовом критерии

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

Итак, в данной задаче выделяется три операции:

Источник

Введение в анализ сложности алгоритмов (часть 1)

От переводчика: данный текст даётся с незначительными сокращениями по причине местами излишней «разжёванности» материала. Автор абсолютно справедливо предупреждает, что отдельные темы покажутся чересчур простыми или общеизвестными. Тем не менее, лично мне этот текст помог упорядочить имеющиеся знания по анализу сложности алгоритмов. Надеюсь, что он будет полезен и кому-то ещё.
Из-за большого объёма оригинальной статьи я разбила её на части, которых в общей сложности будет четыре.
Я (как всегда) буду крайне признательна за любые замечания в личку по улучшению качества перевода.

Введение

Многие современные программисты, пишущие классные и широко распространённые программы, имеют крайне смутное представление о теоретической информатике. Это не мешает им оставаться прекрасными творческими специалистами, и мы благодарны за то, что они создают.

Тем не менее, знание теории тоже имеет свои преимущества и может оказаться весьма полезным. В этой статье, предназначенной для программистов, которые являются хорошими практиками, но имеют слабое представление о теории, я представлю один из наиболее прагматичных программистских инструментов: нотацию «большое О» и анализ сложности алгоритмов. Как человек, который работал как в области академической науки, так и над созданием коммерческого ПО, я считаю эти инструменты по-настоящему полезными на практике. Надеюсь, что после прочтения этой статьи вы сможете применить их к собственному коду, чтобы сделать его ещё лучше. Также этот пост принесёт с собой понимание таких общих терминов, используемых теоретиками информатики, как «большое О», «асимптотическое поведение», «анализ наиболее неблагоприятного случая» и т.п.

Этот текст также ориентирован на учеников средней школы из Греции или любой другой страны, участвующих в Международной олимпиаде по информатике, соревнованиях по алгоритмам для учащихся и тому подобном. Как таковой, он не требует предварительного знания каких-либо сложных математических моментов и просто даст вам основу для дальнейшего исследования алгоритмов с твёрдым пониманием стоящей за ними теории. Как тот, кто в своё время много участвовал в различных состязаниях, я настоятельно рекомендую вам прочитать и понять весь вводный материал. Эти знания будут просто необходимы, когда вы продолжите изучать алгоритмы и различные передовые технологии.

Я надеюсь, что это текст будет полезен для тех программистов-практиков, у которых нет большого опыта в теоретической информатике (то, что самые вдохновлённые инженеры-программисты никогда не ходили в колледж, уже давно свершившийся факт). Но поскольку статья предназначена и для студентов тоже, то временами она будет звучать, как учебник. Более того, некоторые темы могут показаться вам чересчур простыми (например, вы могли сталкиваться с ними во время своего обучения). Так что, если вы чувствуете, что понимаете их — просто пропускайте эти моменты. Другие секции идут несколько глубже и являются более теоретическими, потому что студенты, участвующие в соревнованиях, должны разбираться в теории алгоритмов лучше, чем средний практик. Но знать эти вещи не менее полезно, а следить за ходом повествования не так уж сложно, так что они, скорее всего, заслуживают вашего внимания. Оригинальный текст был направлен учащимся старшей школы, никаких особых математических знаний он не требует, поэтому каждый, имеющий опыт программирования (например, знающий, что такое рекурсия) способен понять его без особых проблем.

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

Нотация «большого О» и анализ сложности алгоритмов — это те вещи, которые и программисты-практики, и студенты-новички часто считают трудными для понимания, боятся или вообще избегают, как бесполезные. Но они не так уж сложны и заумны, как может показаться на первый взгляд. Сложность алгоритма — это всего лишь способ формально измерить, насколько быстро программа или алгоритм работают, что является весьма прагматичной целью. Давайте начнём с небольшой мотивации по этой теме.

Мотивация

Мы уже знаем, что существуют инструменты, измеряющие, насколько быстро работает код. Это программы, называемые профайлерами (profilers), которые определяют время выполнения в миллисекундах, помогая нам выявлять узкие места и оптимизировать их. Но, хотя это и полезный инструмент, он не имеет отношения к сложности алгоритмов. Сложность алгоритма — это то, что основывается на сравнении двух алгоритмов на идеальном уровне, игнорируя низкоуровневые детали вроде реализации языка программирования, «железа», на котором запущена программа, или набора команд в данном CPU. Мы хотим сравнивать алгоритмы с точки зрения того, чем они, собственно, являются: идеи, как происходит вычисление. Подсчёт миллисекунд тут мало поможет. Вполне может оказаться, что плохой алгоритм, написанный на низкоуровневом языке (например, ассемблере) будет намного быстрее, чем хороший алгоритм, написанный языке программирования высокого уровня (например, Python или Ruby). Так что пришло время определиться, что же такое «лучший алгоритм» на самом деле.

Алгоритм — это программа, которая представляет из себя исключительно вычисление, без других часто выполняемых компьютером вещей — сетевых задач или пользовательского ввода-вывода. Анализ сложности позволяет нам узнать, насколько быстра эта программа, когда она совершает вычисления. Примерами чисто вычислительных операций могут послужить операции над числами с плавающей запятой (сложение и умножение), поиск заданного значения из находящейся в ОЗУ базы данных, определение игровым искусственным интеллектом (ИИ) движения своего персонажа таким образом, чтобы он передвигался только на короткое расстояние внутри игрового мира, или запуск шаблона регулярного выражения на соответствие строке. Очевидно, что вычисления встречаются в компьютерных программах повсеместно.

Анализ сложности также позволяет нам объяснить, как будет вести себя алгоритм при возрастании входного потока данных. Если наш алгоритм выполняется одну секунду при 1000 элементах на входе, то как он себя поведёт, если мы удвоим это значение? Будет работать также быстро, в полтора раза быстрее или в четыре раза медленнее? В практике программирования такие предсказания крайне важны. Например, если мы создали алгоритм для web-приложения, работающего с тысячей пользователей, и измерили его время выполнения, то используя анализ сложности, мы получим весьма неплохое представление о том, что случится, когда число пользователей возрастёт до двух тысяч. Для соревнований по построению алгоритмов анализ сложности также даст нам понимание того, как долго будет выполняться наш код на наибольшем из тестов для проверки его правильности. Так что, если мы определим общее поведение нашей программы на небольшом объёме входных данных, то сможем получить хорошее представление и о том, что будет с ней при больших потоках данных. Давайте начнём с простого примера: поиска максимального элемента в массиве.

Подсчёт инструкций

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

Максимальный элемент массива можно найти с помощью простейшего отрывка кода. Например, такого, написанного на Javascript. Дан входной массив А размера n :

Анализ наиболее неблагоприятного случая

В теле цикла мы имеем операции поиска в массиве и сравнения, которые происходят всегда:

Асимптотическое поведение

С полученной выше функцией мы имеем весьма хорошее представление о том, насколько быстр наш алгоритм. Однако, как я и обещал, нам нет нужды постоянно заниматься таким утомительным занятием, как подсчёт команд в программе. Более того, количество инструкций у конкретного процессора, необходимое для реализации каждого положения из используемого языка программирования, зависит от компилятора этого языка и доступного процессору (AMD или Intel Pentium на персональном компьютере, MIPS на Playstation 2 и т.п. ) набора команд. Ранее же мы говорили, что собираемся игнорировать условия такого рода. Поэтому сейчас мы пропустим нашу функцию f через «фильтр» для очищения её от незначительных деталей, на которые теоретики предпочитают не обращать внимания.

Имеет смысл думать о 4 просто как о «константе инициализации». Разным языкам программирования для настройки может потребоваться разное время. Например, Java сначала необходимо инициализировать свою виртуальную машину. А поскольку мы договорились игнорировать различия языков программирования, то попросту отбросим это значение.

эквивалентен следующему на Си:

Так что имеет смысл ожидать, что различные языки программирования будут подвержены влиянию различных факторов, которые отразятся на подсчёте инструкций. В нашем примере, где мы используем «немой» паскалевский компилятор, игнорирующий возможности оптимизации, требуется по три инструкции на Паскале для каждого доступа к элементу массива вместо одной на Си. Пренебрежение этим фактором идёт в русле игнорирования различий между конкретными языками программирования с сосредоточением на анализе самой идеи алгоритма как таковой.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *