Пояснення відповідності асимптотичної складності алгоритмів практиці проектування алгоритмів


40

В алгоритмах і складності ми орієнтуємося на асимптотичну складність алгоритмів, тобто кількість ресурсів, які алгоритм використовує, оскільки розмір вхідного сигналу йде до нескінченності.

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

Алгоритм, який добре працює на практиці в кінцевій кількості екземплярів, які нас цікавлять, не повинен мати хорошої асимптотичної складності (хороша продуктивність у кінцевій кількості екземплярів нічого не означає про асимптотичну складність). Аналогічно, алгоритм з хорошою асимптотичною складністю може не працювати на практиці на кінцевій кількості випадків, які нас цікавлять (наприклад, через великі постійні).

Чому ми використовуємо асимптотичну складність? Як ці асимптотичні аналізи пов'язані з проектуванням алгоритмів на практиці?


Відповіді:


24

Цікаве питання: яка альтернатива? Єдиний інший мені відомий метод - тестування / тестування. Ми програмуємо алгоритми, нехай вони працюють (репрезентативний зразок) кінцевого набору входів і порівнюють результати. З цим є пара проблем.

  • Результати не є загальними щодо машин. Запустіть свій орієнтир на іншому комп’ютері, і ви отримаєте різні результати напевно, кількісно, ​​а може навіть і якісно.
  • Результати не є загальними щодо мов програмування. Різні мови можуть спричинити дуже різні результати.
  • Результати не є загальними щодо деталізації реалізації. Ви буквально порівнюєте програми , а не алгоритми; невеликі зміни в реалізації можуть спричинити величезні відмінності в продуктивності.
  • Якщо найгірший випадок рідкісний, вибірковий вхідний зразок не може містити поганий екземпляр. Це справедливо, якщо ви переймаєтесь середньою ефективністю справи, але деякі середовища вимагають найгірших гарантій.
  • На практиці змінюються набори входів. Зазвичай введення з часом збільшуються. Якщо ви не повторюєте свій показник кожні півроку (так, деякі дані зростають так швидко), ваші результати незабаром втрачають силу ”.

Сказане, ігнорування всіляких ефектів і констант в аналізі є типовим, але його можна назвати ледачим (щодо практики). Він служить для порівняння алгоритмічних ідей більше, ніж для точного визначення ефективності заданої (навіть псевдокоду) реалізації. Громадському загальновідомо, що це грубо і що часто потрібно пильніший погляд; наприклад, Quicksort менш ефективний, ніж сортування вставки для (дуже) малих входів. Якщо бути справедливим, точніший аналіз зазвичай важкий ².

Іншим, апостеріорним обґрунтуванням формальної, абстрактної точки зору є те, що на цьому рівні речі часто зрозуміліші. Таким чином, десятиліття теоретичного вивчення породили безліч алгоритмічних ідей та структур даних, які використовуються на практиці. Теоретично оптимальний алгоритм - це не завжди той, який ви хочете використовувати на практиці - є й інші міркування, але ефективність для досягнення; Подумайте, кучки Фібоначчі - і ця мітка може бути навіть не унікальною. Типовому програмісту, який займається оптимізацією арифметичних виразів, важко придумати нову ідею на цьому рівні (не сказати, що цього не відбувається); вона може (і повинна) здійснити ці оптимізації щодо засвоєної ідеї.

Існують формальні, теоретичні інструменти, які дозволяють певною мірою закрити прогалину для практики. Приклади є

  • враховуючи ієрархію пам'яті (та інші введення / виведення),
  • аналізуючи середній випадок (де це доречно),
  • аналіз номерів окремих тверджень (замість абстрактних заходів витрат) та
  • визначення постійних факторів.

Наприклад, Кнут відомий тим, що буквально підраховує кількість різних операторів (для даної реалізації в даній моделі), що дозволяє точно порівняти алгоритми. Такий підхід неможливий на абстрактному рівні, і це важко зробити у більш складних моделях (думаю, Java). Див. [4] сучасний приклад.

Завжди буде розрив між теорією та практикою. В даний час ми працюємо над інструментом³ з метою поєднання найкращого з обох світів, щоб зробити надійні прогнози як для алгоритмічних витрат, так і для виконання (в середньому), але поки що нам не вдалося усунути сценарії, коли один алгоритм має вищу коштує, але менший час виконання (на деяких машинах), ніж еквівалентний (хоча ми можемо виявити це і підтримати пошук причини).

Я рекомендую практикам використовувати теорію для фільтрації простору алгоритмів перед запуском тестів:

if ( input size forever bounded? ) {
  benchmark available implementations, choose best
  schedule new benchmarks for when machine changes
}
else {
  benchmark implementations of all asymptotically good algorithms
  choose the best
  schedule new benchmarks for when machine changes or inputs grow significantly
}

  1. Після абсолютної та відносної продуктивності можуть відбуватися шалені зміни, коли кількість кеш-пропусків збільшується, що, як правило, відбувається при зростанні входів, але машина залишається такою ж.
  2. Як і в Росії, провідні дослідники в цій галузі не в змозі цього зробити.
  3. Знайдіть інструмент тут . Приклад використання було опубліковано в програмі Dual Pivot Quicksort за допомогою MaLiJAn від Engineering Wild та ін. (2012) [ додрук ]
  4. Середній аналіз випадків подвійного зсувного кікспорта Java 7 від С. Wild and M. Nebel (2012) - [ препринт ]

3
Можливо, чистий акт вивчення теорії алгоритмів загострить ваше око і навчить ваш абстракційний мозок для алгоритмів, даючи вам ще один інструмент для оцінки коду в програмі щоденного програмування. Абстрагуйте подалі від коду, оцініть принцип, вдосконаліть його та перекладіть назад до коду. Приклад: "А, я бачу, ви хочете запрограмувати словник. Але ви, по суті, списки програм; чому б не спробувати дерева?"
Рафаель

Межі асимптотичного аналізу стають очевидними, коли копаєтеся глибше; Квікорт - яскравий приклад .
Рафаель

1
FWIW, я написав до більш свіжий знімок моєї думки про Ландау нотації тут .
Рафаель

11

Я припускаю, що це питання виникає при викладанні курсу, який включає асимптотичний аналіз. Є кілька можливих відповідей на те, чому цей матеріал викладають у вступних класах:

  • Асимптотичний аналіз - це математична абстракція, яка піддається аналізу. Як (мабуть) математики, ми хочемо вміти аналізувати алгоритми, і вони єдиним способом приборкати їх складність використовують асимптотичний аналіз.

  • Оцінка асимптотичної продуктивності алгоритму вказує на деякі корисні на практиці принципи: наприклад, сконцентруйтесь на тій частині коду, яка займає більшу частину часу, та знижте будь-яку частину коду, яка займає асимптотично незначну частину часу .

  • Деякі методики асимптотичного аналізу є корисними. Я маю на увазі тут головним чином так звану "головну теорему", яка за багатьох обставин є хорошим описом реальності.

  • Існує також історична причина: коли люди вперше почали аналізувати алгоритми, вони щиро думали, що асимптотична складність відображає практичне використання. Однак з часом вони виявилися неправильними. Те ж саме сталося з P як класом ефективно розв'язуваних задач, і NP як класом нерозв'язних задач, обидві з яких вводять в оману на практиці.

Особисто я вважаю, що асимптотичний аналіз є розумною частиною навчальної програми. Більш сумнівні частини включають теорію формальної мови та теорію складності (все, що стосується машини Тьюрінга). Деякі люди стверджують, що, хоча ці предмети самі по собі не корисні потенційному програмісту, вони вселяють їй певну думку, необхідну для того, щоб бути добрим лікарем. Інші стверджують, що теорія іноді впливає на практику, і цих рідкісних випадків достатньо, щоб обґрунтувати викладання цих досить затаємничих предметів загальній аудиторії інформатики. Я вважаю за краще, щоб вони вивчали історію чи літературу чи будь-який інший предмет, який їх насправді цікавить; обидва є настільки ж актуальними для їх майбутніх перспектив роботи і для них важливіші, як люди.


Дякую Ювал. Мотивація, в основному, цікавить, як пояснити студентам корисність асимптотичного аналізу та його відповідність практиці проектування та використання алгоритмів у реальних програмах (де більшість випадків зрозуміло, що нас цікавить лише кінцева, хоча й можливо дуже велика кількість примірників), не виправдовуючи навчальну програму.
Каве

1
Мене бентежить ваше приміщення. Ви, мабуть, припускаєте, що цільова група - це і математики, і прагнучі програмісти, що є дивним поєднанням і не характеризує комп'ютерних науковців. (Також я не поділяю вашу думку щодо формальних мов, але це інша тема.)
Рафаель

Навпаки, я припускаю, що цільова група прагне програмістів. Однак значна частина навчальної програми існує заради теоретиків-комп’ютерів. Звичайно, ці дві групи мають суперечливі потреби. Оскільки більшість студентів є потенційними програмістами, я вважаю, що навчальна програма повинна бути спрямована на них, але деякі вчені не згодні. Можливо, вони хочуть навчити майбутніх професорів. Можливо, ви можете пояснити їхню точку зору.
Yuval Filmus

3
@YuvalFilmus Я часто пояснював, що не вірю, що CS = TCS + програмування. Якщо ви викладаєте курс CS (в університеті), і більшість ваших студентів хочуть бути програмістами, щось порушено (imho). Я заперечую, що будь-який комп'ютерний вчений може отримати прибуток від ґрунтовної освіти алгоритміки, формальних мов і навіть якоїсь теорії складності (та багатьох інших речей, наприклад, як працюють компілятори та процесори).
Рафаель

2
@Wildcard Комп'ютерна архітектура, комп'ютерна графіка, AI, дослідження мови програмування, ... - список нескінченний! TCS справді є нішею, а програмування є лише інструментом для (більшості) дослідників CS.
Рафаель

7

Існує дві серйозні причини використовувати асимптотичний аналіз часу роботи:

  • абстрагувати далеко неважливі деталі. У багатьох програмах, де нам потрібні нетривіальні алгоритми, більшість часу витрачається на проблемні екземпляри, які вимагають середньої та великої кількості операцій, і нас більше цікавить загальна тенденція, ніж точний підрахунок операцій. У цих додатках поведінка для малих нецікаво.n

  • щоб дозволити математичну простежуваність. Випадки, такі, що можна знайти точні вирази для кількості операцій, є винятковими. Вивчення асимптотики відкриває більше можливостей (як-от асимптотичні наближення складних функцій зручні).

І є багато інших (як машинна незалежність, осмисленість, порівнянність ...).


"нас більше цікавить загальна тенденція, ніж точний підрахунок операцій" - це речення не є правдивим. Це виправдання підручника, яке не в усіх програмах. "Оптимізація алгоритму корисна для середньої та великої кількості операцій" - також це не є. Алгоритм, який завжди виконується на невеликих входах і швидкий, але виконується мільярди разів, також варто оптимізувати. Практичний приклад: кожна реальна реалізація Quicksort переходить на інший алгоритм сортування для малих . n
Рафаель

Ну, я не думаю, що це взагалі правило. Чим більше даних ви викидаєте, тим слабкіші заяви ви можете зробити. Асимптотична (і, тим більше, "велика-ох") перспектива створює твердження на кшталт "Quicksort швидше, ніж Insertionsort", що, якщо не помилково, теж не зовсім правдиво. (Так, я кажу, що алгоритм аналізу часто навчають неправильно, імхо.)
Рафаель

6

Як зазначається у відповіді Рафаеля, точне обчислення найгіршого часу роботи може бути дуже важким. Точні обчислення також можуть бути непотрібними, оскільки модель ОЗУ вже вводить наближення. Наприклад, чи дійсно всі операції займають однаковий час? Конкретні реалізації (апаратні засоби, оптимізації) можуть пришвидшити алгоритм постійними чинниками. Ми хочемо зрозуміти, наскільки ефективний алгоритм не залежить від цих факторів. Це велика мотивація використання асимптотичного аналізу.


3

Тому що асимптотика "проста" (ну, простіше, ніж робити точний аналіз для кінцевих випадків).

Порівняйте, наприклад, енциклопедичну книгу "Мистецтво комп’ютерного програмування" Кнута, яка робить детальний аналіз усіх важливих алгоритмів (і багатьох не дуже важливих) з аналізом "великого пальця", який часто достатній для отримання асимптотичної оцінки ( або просто пов'язане), як це практикується в більшості книг про "алгоритми".

Ви, звичайно, праві. Якщо проблема є досить важливою, аналіз у стилі Кнут (або, можливо, трохи менш детальний) аналіз може бути гарантованим. У багатьох випадках натяк на асимптотичну складність (можливо, середню з дисперсією) підходить для експериментальних даних. У більшості випадків зробити грубу класифікацію конкуруючих алгоритмів, оскільки перший раунд висіву порівняння асимптотики може бути досить точним. А якщо немає претендентів, то погана новина про точну вартість детально - це мазохізм.


2
Це лише половина правди: по-перше, здається, ви пишете з урахуванням "великий-о-о" (про яке питання не йдеться). По-друге, асимптотики "великих-ох" відомі тим, що ефектно не спрацьовують для "обрізання бур'янів" під час вибору алгоритмів: вхідні дані є дійсними.
Рафаель

3

Під асимптотичним аналізом я припускаю, що ми маємо на увазі поведінку алгоритму, оскільки розмір вхідного сигналу йде до нескінченності.

Причина, по якій ми використовуємо асимптотичний аналіз, полягає в тому, що вона корисна для прогнозування поведінки алгоритмів на практиці . Прогнози дозволяють нам приймати рішення, наприклад, коли у нас є різні алгоритми для проблеми, яку нам слід використовувати? (Бути корисним не означає, що це завжди правильно.)

Це ж питання можна задати про будь-яку спрощену модель реального світу. Чому ми використовуємо спрощені математичні моделі реального світу?

Подумайте про фізику. Класична ньютонівська фізика не така хороша, як релятивістська фізика в прогнозуванні реального світу. Але це досить хороша модель для будівництва автомобілів, хмарочосів, підводних човнів, літаків, мостів тощо. Є випадки, коли це недостатньо добре, наприклад, якщо ми хочемо побудувати супутник або відправити космічний зонд до Плутона або передбачити рух масивних небесних об'єктів, таких як зірки і планети або дуже швидкісні об'єкти, як електрони. Важливо знати, які межі моделі.

  1. Зазвичай це досить хороше наближення до реального світу. На практиці ми часто бачимо, що алгоритм з кращим асимптотичним аналізом працює краще на практиці. Рідко буває так, що алгоритм має кращу асимптотичну поведінку. Отже, якщо входи можуть бути достатньо великими, то, як правило, ми можемо розраховувати на асимптотичний аналіз як на перший прогноз поведінки алгоритмів. Це не так, якщо ми знаємо, що вхід буде малим. Залежно від ефективності, яку ми хочемо, нам може знадобитися зробити більш ретельний аналіз, наприклад, якщо у нас є інформація про розподіл входів, алгоритм буде наданий, ми можемо зробити більш ретельний аналіз для досягнення поставлених цілей (наприклад, швидкий на 99 % входів). Справа, як перший крок, асимптотичний аналіз є гарною відправною точкою. На практиці ми також повинні робити тести на працездатність, але майте на увазі, що це також має свої проблеми.

  2. AAAмає кращу асимптотичну складність. Що жоден з них не кращий за інший у всіх входах? Тоді вона стає більш хитрою і залежить від того, що нас хвилює. Чи ми дбаємо про великі входи чи малі входи? Якщо ми дбаємо про великі входи, то нечасто алгоритм має кращу асимптотичну складність, але погіршує себе на великих входах, які нас цікавлять. Якщо ми дбаємо більше про невеликі введення, то асимптотичний аналіз може виявитися не таким корисним. Ми повинні порівнювати час роботи алгоритмів на входах, які нас цікавлять. На практиці для складних завдань із складними вимогами асимптотичний аналіз може бути не таким корисним. Для простих основних проблем, які охоплюють підручники алгоритму, це досить корисно.

Коротше кажучи, асимптотична складність порівняно легко обчислити наближення фактичної складності алгоритмів для простих основних завдань (проблеми в підручнику з алгоритмами). Оскільки ми будуємо складніші програми, вимоги до продуктивності змінюються та ускладнюються, а асимптотичний аналіз може виявитися не настільки корисним.


Добре порівнювати асимптотичний аналіз з іншими підходами для прогнозування продуктивності алгоритмів та їх порівняння. Одним із загальних підходів є тести на ефективність щодо випадкових або контрольних входів. Це часто, коли обчислення асимптотичної складності є важким або нездійсненним, наприклад, коли ми використовуємо евристику, як, наприклад, рішення SAT. Інший випадок, коли вимоги є складнішими, наприклад, коли продуктивність програми залежить від зовнішніх факторів, і нашою метою може бути те, що закінчується в певні встановлені часові рамки (наприклад, подумайте про оновлення інтерфейсу, показаного користувачеві) на 99% входи.

Але майте на увазі, що аналіз ефективності також має свої проблеми. Це не дає математичних грантів на ефективність на меншій мірі, ми фактично виконуємо тест на ефективність на всіх входах, які будуть задані алгоритму (часто обчислювально непереборним) (і часто неможливо вирішити, що деякі входи ніколи не будуть надані). Якщо ми протестуємо на випадковій вибірці або еталоні, ми неявно припускаємо деяку закономірність щодо роботи алгоритмів, тобто алгоритм буде виконувати аналогічно на інших входах, які не були частиною тесту на ефективність.

Друге питання тестів на ефективність полягає в тому, що вони залежать від тестового середовища. Тобто продуктивність програми не визначається лише вхідними даними, а зовнішніми факторами (наприклад, тип машини, операційна система, ефективність кодованого алгоритму, використання центрального процесора, час доступу до пам'яті тощо), деякі з яких можуть змінюватися в різних режимах роботи тест на одній машині. Тут ми знову припускаємо, що конкретні середовища, в яких проводиться тест продуктивності, аналогічні фактичному середовищу, якщо ми не робимо тести на ефективність у всіх середовищах, на яких ми можемо запустити програму (і як ми можемо передбачити, на яких машинах хтось може запустити сортування алгоритм включення через 10 років?).

Θ(nlgn)Θ(n2)Θ(lgn)O(n)



Мені подобається ця відповідь достатньо, щоб зараз підняти підсумки. Дві примітки: 1) Я б тут використав "вартість" замість "складності". Частково з міркувань домашніх улюбленців, але також тому, що існує багато можливих заходів щодо витрат (що ускладнює всі ваші міркування). 2) Можливо, ви хочете зробити мовний польський пропуск. ;)
Рафаель

@Raphael, спасибі Я скоро планую ще одну редакцію. :)
Каве

-2

O(n2)O(nlogn)O(n2) щоб він закінчився порівняно з кваксортом.

тепер уявіть, що чекання повторюється в коді стільки разів, скільки викликається код. як можна математично кількісно оцінити / обґрунтувати цю очевидну перевагу алгоритму швидкості? (тобто чи справді його назва виправдана чи це просто маркетинговий слоган?) за допомогою асимптотичних вимірювань складності. залишається дивитися на анімацію, суб'єктивно відчуваючи, що пухирці - це якось слабший алгоритм, і аналіз асимптотичної складності може це довести кількісно. але зауважте, що асимптотичний аналіз складності - це лише один інструмент у пакеті інструментів для аналізу алгоритмів, і це не завжди є кінцевим.

і варто також дивитися на бічний код також. Бульборт здається концептуально простішим і не використовує рекурсії. quicksort - це не настільки зрозумілі негайно принципи "медіани 3". Бульборт може бути реалізований просто в циклі без підпрограми, тоді як у швидкодіючої вибірки може бути принаймні одна підпрограма. це показує схему, що більш досконалість коду може іноді покращити асимптотичну складність за рахунок простоти коду. іноді трапляється надзвичайна торгівля, схожа на концепцію зменшення граничної віддачі (походить від економіки), коли дуже великі амти складності коду [вимагають цілих робіт, наповнених thms і доказами для обгрунтування] лише купують дуже невеликі поліпшення асимптотичної складності. це показано як приклад espматричне множення і навіть може бути схоплено .


Існує багато території між "переглядом анімації" та формальним аналізом, наприклад, великі показники виконання. Вони фактично є власною власною областю, оскільки у нас немає теорії, яка б пояснювала все, що впливає на час виконання.
Рафаель

@raphael ви відповідали на тестування у своїй відповіді; це гарна відповідь. але зауважте, що анімація / візуалізація може бути тісно пов’язана з тестуванням. насправді є багато пояснень того, що впливає на час виконання [висвітлюється в інших відповідях], але певною мірою його «шум» та асимптотична складність «згладжує / в середньому шумує». ось ще одна вправа, щоб побачити, як це насправді це робить.
vzn

Анімації, однак, не фільтрують шум. Плюс людське око легко піддається обману, і просто неможливо дивитись анімації для вибірки з розумним розміром списків розумного розміру (скажімо, 1000 списків для розмірів у мільйонах для порівняльних алгоритмів сортування) та вирішувати, який алгоритм був швидшим (в середньому).
Рафаель

nn

n
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.