簡體   English   中英

討論小n的計算復雜性的正確方法

[英]Right way to discuss computational complexity for small n

在討論計算復雜性時,似乎每個人都會直接進入Big O.

讓我們說例如我有一個混合算法,如合並排序,它使用插入排序較小的子陣列(我相信這稱為平鋪合並排序 )。 它仍然最終與O(n log n)合並排序,但我想討論小n的算法的行為/特征,在沒有實際合並的情況下。

對於所有意圖和目的,平鋪合並排序插入排序,對我的小n的域執行完全相同的指令。 然而,Big O處理大型和漸近的情況並且討論小O的Big O幾乎是矛盾的。 在這種情況下,人們甚至認為“行為就像一個O(n ^ 2)算法”,對我大吼大叫“。 在形式理論計算分析的背景下,在小n的情況下描述算法行為的正確方法是什么? 為了澄清,不僅在n很小的情況下,而且在n從不大的情況下。

有人可能會說,對於這么小的n並不重要,但我對它的情況感興趣,例如有一個很大的常數,例如執行多次,並且在實踐中它顯示出明顯的趨勢並且是主導因素。 例如,下圖中顯示的初始二次增長。 我不是在解雇Big O,更多的是要求一種正確告訴雙方故事的方法。

在此輸入圖像描述


[ 編輯 ]

如果對於“小n ”,常數可以輕松地去除所有生長速率的痕跡

  1. 只討論了漸近的情況,在這種情況下,與任何實際應用的關聯性較小,或者
  2. 必須有一個閾值,我們同意n不再是“小”。

那么n不是“小”的情況( n足夠大,以至於增長率不會受到任何實際常數的顯着影響),但還不足以顯示最終的漸近增長率,因此只能看到子增長率(例如上圖中的形狀)?

是否沒有表現出這種行為的實用算法? 即使沒有,理論上的討論仍然是可能的。 我們是否僅僅因為“應該做什么”來衡量而不是僅僅討論理論? 如果在所有實際案例中都觀察到某種行為,為什么不存在有意義的理論呢?


讓我轉向另一個問題。 我有一個顯示分段超線性步驟的圖表。 聽起來很多人會說“這是一個純粹的巧合,它可以是任何可以想象的形狀”(當然極端)並且如果它是正弦波而不會擊打眼瞼。 我知道在很多情況下,形狀可以被常數隱藏,但這里很明顯。 我怎樣才能正式解釋圖形產生這種形狀的原因?

我特別喜歡@Sneftel的話“不精確但有用的指導”。

我知道Big O和漸近分析不適用。 什么是? 我能走多遠?

在聊天中討論

重要的是要記住,漸近分析是一種分析簡化 ,而不是分析算法的任務。 例如,選擇排序。 是的,它在O(n^2)時間內執行。 但它也正確地執行n*(n-1)/2比較和n-1-k交換,其中k是從正確位置開始的元素數(除了最大值)。 漸近分析是一種簡化性能分析(否則通常是不切實際的)任務的工具,如果我們對“真正的大n”段不感興趣,我們可以放棄。

你可以選擇表達你的界限。 假設一個函數需要精確的n + floor(0.01*2^n)運算。 當然,那是指數時間。 但也可以說“對於最多10個元素的數據大小,該算法需要n2*n操作。” 后者不是描述曲線的形狀,而是圍繞該曲線的包絡,在特定的用例范圍內給出關於算法實用性的不精確但有用的指導。

對於小n,計算復雜性 - 當n向無窮大增加時事物如何變化 - 沒有意義,因為其他效應占主導地位。

我已經看過哪些論文討論n的小值的行為,通過測量實際系統上的算法來做,並討論算法如何在實踐中而不是從理論的角度來執行。 例如,對於您添加到帖子中的圖表,我會說'此圖表演示了整體的O(N)漸近行為,但每個圖塊內的增長是有界的二次'。

我不知道從理論角度討論這種行為會有意義的情況 - 眾所周知,對於小n來說,實際效果超過了縮放的影響。

復雜性不是關於一台機器上的一個n執行時間,因此即使常量很大也不需要考慮它。 復雜性告訴您輸入的大小如何影響執行時間。 對於小n ,您可以將執行時間視為常量。 這是一方面。

從第二方面你說:

  1. 你有一個混合算法在O(n log n)n大於某個kO(n^2) n小於k
  2. 常數k非常大,算法運算緩慢。

這種算法沒有意義,因為你可以很容易地改進它。

讓我們采取Red-black tree 此樹上的操作以O(n log n)時間復雜度執行,但存在大的常量。 因此,在某些情況下,在普通機器上,它可能運行緩慢(即比簡單的解決方案慢)。 在分析復雜性時沒有必要考慮它。 在系統中實現它時需要考慮它:您需要檢查它是否是最佳選擇,考慮它將使用的實際機器以及它將解決的問題。

你是對的。

對於小n ,即僅執行插入排序時,漸近行為是二次O(n^2 )。

對於較大的n ,當平鋪合並排序進入播放時,行為切換到O(n.Log(n))

如果你記得每個行為都有其有效域,在切換閾值之前,讓N和之后,就沒有矛盾了。

在實踐中, N周圍的曲線之間會有平滑的混合。 但在實踐中, N值太小,以至於二次行為沒有足夠的“空間”來表現自己。

處理這種分析的另一種方法是說N是常數,插入排序需要恆定的時間。 但我不同意說這是必須的。

讓我們解開一些事情。 Big-O是用於描述函數增長率的工具。 通常應用的功能之一是在特定抽象機器上執行的長度為n的輸入上的算法的最壞情況運行時間。 我們經常忘記最后一部分,因為有一大類具有隨機存取存儲器的機器可以只用常數因子減速模擬彼此,並且在特定的大O運行時限內可解決的問題類別是等價的穿過這些機器。

如果您想談論小輸入的復雜性,那么您需要測量常數因子。 一種方法是測量實際實現的運行時間。 人們通常在物理機器上執行此操作,但如果您像Knuth一樣是硬核,那么您可以使用指令時序創建自己的匯編語言。 另一種方法是測量易於識別的東西,但也是執行其他工作的有用代理。 對於比較分類,這可以是比較。 對於數值算法,這通常是浮點運算。

閱讀Knuth的“計算機編程藝術系列”,從“第1卷基礎算法”開始,“1.2.10:算法分析”一節。 在那里,他展示了(以及在他的所有其他開創性工作中)如何使用合適的參考機器對任意問題大小進行精確分析,通過對每個處理器指令進行詳細的普查。

這種分析不僅要考慮問題的大小,還要考慮影響運行時間的輸入數據分布的任何相關方面。 為簡化起見,分析通常僅限於研究最壞情況預期情況輸出敏感情況 ,而不是一般統計特征。 為了進一步簡化,使用漸近分析。

不計算除了瑣碎的算法之外,詳細的方法在數學上具有很大的挑戰性,它在現代機器上變得不切實際。 實際上,它依賴於類似於所謂的RAM模型的處理器行為,該模型假定每個指令和每個存儲器訪問的時間恆定http://en.wikipedia.org/wiki/Random-access_machine )。 除了可能將特殊硬件組合到硬實時操作系統之外,這些假設現在完全錯誤。

當你有一個時間復雜度為O(n ^ 2)的算法時,你還有另一個具有時間復雜度的算法,比如說O(n)。然后從這兩個時間復雜度中你不能得出后一種算法的結論。對於所有輸入值,它比前一個更快。你只能說后一種算法漸近(比較大的輸入值的意思)比前一種算法更快。這里你必須記住這樣一個事實:在漸近符號的情況下,常數因子通常被忽略以增加算法的時間復雜度的理解能力。例如:marge sort在O(nlogn)最壞情況時間運行,插入排序在O(n ^ 2)最壞情況時間運行。但是插入排序中隱藏的常數因子小於marge排序,實際上插入排序可以比許多機器上的小問題大小更快。

漸近符號並不描述算法的實際運行時間。實際運行時間依賴於機器,因為不同的機器具有不同的架構和不同的指令周期執行時間。漸近符號只是漸近地描述了算法相對於其他算法的速度。但它沒有描述算法在小輸入值(n <= no)的情況下的行為.no(閾值)的值取決於隱藏的常數因子和低階項。隱藏的常數因子依賴於它將被執行的機器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM