تقسیم‌و‌غلبه برای ضرب ماتریس: از رویکرد ساده تا الگوریتم اشتراسن

ضرب دو ماتریس یک عملیات بنیادین در علوم کامپیوتر است، و رویکرد ساده بسیار دور از بهینه است. این راهنمای جامع الگوریتم استاندارد ضرب ماتریس با زمان مکعبی را توضیح می‌دهد، نشان می‌دهد چگونه یک رویکرد تقسیم‌و‌غلبه ساده در بهبود آن شکست می‌خورد، و الگوریتم قابل‌توجه اشتراسن که به یک زمان اجرای مجانبی واقعاً سریع‌تر می‌رسد را مرور می‌کند.

ضرب ماتریسپالگوریتم اشتراسنتقسیم‌و‌غلبه

~5 دقیقه مطالعه · آخرین به‌روزرسانی ۱۶ شهریور ۱۴۰۵

مسئله ضرب ماتریس

با داشتن دو ماتریس n × n به نام A و B، هدف محاسبه حاصل‌ضرب آن‌ها C = A × B است، که هر عنصرش این‌طور تعریف می‌شود:

C[i][j] = Σ (برای k = 1 تا n) A[i][k] × B[k][j]

این عملیات در سراسر علوم کامپیوتر و ریاضیات کاربردی ظاهر می‌شود، از تبدیلات گرافیک کامپیوتری تا حل سیستم‌های معادلات خطی تا محاسبات شبکه عصبی که یادگیری ماشین امروزی زیربنای آن‌هاست.

الگوریتم ساده

رویکرد ساده مستقیماً تعریف ریاضی را با استفاده از سه حلقه تودرتو پیاده‌سازی می‌کند.

SQUARE-MATRIX-MULTIPLY(A, B, n):
  یک ماتریس جدید n × n به نام C بساز
  برای i = 1 تا n:
      برای j = 1 تا n:
          C[i][j] = 0
          برای k = 1 تا n:
              C[i][j] = C[i][j] + A[i][k] · B[k][j]
  C را برگردان

هر عنصر از ماتریس خروجی نیازمند n ضرب و جمع است، و عنصر برای محاسبه وجود دارد، که زمان اجرای کلی Θ(n³) می‌دهد. برای دهه‌ها، این زمان اجرای مکعبی اساساً اجتناب‌ناپذیر برای ضرب ماتریس فرض می‌شد.

یک تلاش اول: تقسیم‌و‌غلبه ساده

با به‌کارگیری الگوی تقسیم‌و‌غلبه، یک ماتریس n × n می‌تواند به چهار زیرماتریس n/2 × n/2 افراز شود، و ضرب ماتریس می‌تواند به‌صورت بازگشتی برحسب این زیرماتریس‌ها بیان شود.

افراز A و B به ربع‌ها:
A = [A11  A12]      B = [B11  B12]
    [A21  A22]          [B21  B22]

حاصل‌ضرب C = A × B سپس این‌طور است:
C11 = A11·B11 + A12·B21
C12 = A11·B12 + A12·B22
C21 = A21·B11 + A22·B21
C22 = A21·B12 + A22·B22

این نیازمند ۸ ضرب بازگشتی از زیرماتریس‌های n/2 × n/2 است، به‌علاوه ۴ جمع از ماتریس‌های n/2 × n/2، که هرکدام زمان Θ(n²) می‌گیرند. رابطه بازگشتی حاصل این است:

T(n) = 8T(n/2) + Θ(n²)

حل این رابطه بازگشتی، با استفاده از روش استاد که در مقاله بعدی این مجموعه پوشش داده می‌شود، T(n) = Θ(n³) می‌دهد — دقیقاً همان زمان اجرای مجانبی الگوریتم سه‌حلقه ساده. صرفاً بازنویسی بازگشتی مسئله هیچ بهبودی فراهم نکرد.

بینش پیشگامانه اشتراسن

در سال ۱۹۶۹، فولکر اشتراسن راهی برای محاسبه حاصل‌ضرب دو ماتریس ۲×۲ با استفاده از فقط ۷ ضرب به‌جای ۸ کشف کرد، به قیمت جمع و تفریق‌های اضافی ماتریسی. از آنجا که ضرب‌ها عملیات گران‌تری هستند از نظر مجانبی وقتی به‌طور بازگشتی اعمال شوند، این کاهش کوچک تأثیر نامتناسب بزرگی روی زمان اجرای کلی دارد.

الگوریتم اشتراسن ابتدا ۷ حاصل‌ضرب میانی را با استفاده از ترکیب‌های خاصی از مجموع‌ها و تفاضل‌های زیرماتریس محاسبه می‌کند:

P1 = A11 · (B12 - B22)
P2 = (A11 + A12) · B22
P3 = (A21 + A22) · B11
P4 = A22 · (B21 - B11)
P5 = (A11 + A22) · (B11 + B22)
P6 = (A12 - A22) · (B21 + B22)
P7 = (A11 - A21) · (B11 + B12)

چهار ربع خروجی سپس صرفاً از این ۷ حاصل‌ضرب، با استفاده فقط از جمع و تفریق، بازسازی می‌شوند:

C11 = P5 + P4 - P2 + P6
C12 = P1 + P2
C21 = P3 + P4
C22 = P5 + P1 - P3 - P7

تأیید این فرمول‌ها از نظر جبری تأیید می‌کند دقیقاً همان نتیجه فرمول‌های ضرب ماتریس استاندارد را تولید می‌کنند، اما با یک ضرب کمتر در هر سطح بازگشت.

تحلیل زمان اجرای اشتراسن

از آنجا که هر سطح بازگشت اکنون فقط نیازمند ۷ ضرب بازگشتی از زیرماتریس‌های نصف‌اندازه است، به‌علاوه تعداد ثابتی جمع و تفریق Θ(n²)، رابطه بازگشتی این‌طور می‌شود:

T(n) = 7T(n/2) + Θ(n²)

حل این رابطه بازگشتی با استفاده از روش استاد T(n) = Θ(n^log₂7) ≈ Θ(n^2.807) می‌دهد، یک بهبود مجانبی واقعی نسبت به الگوریتم ساده Θ(n³). در حالی که بهبود از توان ۳ به تقریباً ۲.۸۰۷ ممکن است متوسط به‌نظر برسد، برای ماتریس‌های بسیار بزرگ معنادار می‌شود، و چیزی عمیقاً مهم را اثبات کرد: زمان مکعبی اساساً برای ضرب ماتریس مورد نیاز نیست، که در را برای دهه‌ها پژوهش بیشتر روی الگوریتم‌های حتی سریع‌تر باز کرد.

ملاحظات عملی

با وجود پیچیدگی مجانبی بهتر، الگوریتم اشتراسن به‌ندرت در عمل برای اندازه‌های معمول ماتریس استفاده می‌شود، به چند دلیل عملی. الگوریتم یک فاکتور ثابت بزرگ‌تری دارد که درون نمادگذاری مجانبی پنهان است، به این معنا که فقط وقتی ماتریس‌ها به‌اندازه کافی بزرگ شوند از الگوریتم ساده پیشی می‌گیرد. همچنین از نظر عددی کمتر پایدار از رویکرد ساده است، چون جمع و تفریق‌های اضافی می‌توانند خطاهای گرد کردن ممیز شناور را تشدید کنند. کتابخانه‌های عددی دنیای واقعی معمولاً از یک رویکرد ترکیبی استفاده می‌کنند: به‌کارگیری بازگشتی الگوریتم اشتراسن تا یک اندازه آستانه، سپس تغییر به الگوریتم ساده برای حالت پایه، تا بهره مجانبی را با کمینه کردن سربار و بی‌ثباتی عددی به دست آورد.

چرا این نتیجه فراتر از ضرب ماتریس اهمیت دارد

الگوریتم اشتراسن از نظر تاریخی بسیار فراتر از کاربرد عملی فوری‌اش اهمیت دارد. این یکی از اولین نتایجی بود که نشان داد الگوریتم ساده یک مسئله، هرچند شهودی، لزوماً از نظر مجانبی بهینه نیست، و کل یک زیرشاخه پژوهشی درباره ضرب ماتریس سریع را الهام بخشید که تا امروز ادامه دارد، با بهترین الگوریتم‌های شناخته‌شده فعلی که به توان‌هایی حتی کمتر از کران اصلی اشتراسن دست می‌یابند، هرچند با فاکتورهای ثابت به‌اندازه‌ای بزرگ که صرفاً از نظر تئوری جالب باقی می‌مانند.

نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

ساختارهای داده ابتدایی: پشته‌ها، صف‌ها، لیست‌های پیوندی، و درخت‌ها

پیش از پرداختن به ساختارهای داده پیشرفته، تسلط بر بلوک‌های سازنده ابتدایی ضروری است، چون تقریباً هر ساختار پیچیده‌ای از این پایه‌ها ساخته می‌شود. این راهنمای جامع پشته‌ها و صف‌های مبتنی بر آرایه، لیست‌های پیوندی تکی و دوگانه، و تکنیک‌های استاندارد نمایش درخت‌های ریشه‌دار را پوشش می‌دهد، شامل نمایش ظریف فرزند-چپ راهبر-راست برای درخت‌هایی با شاخه‌بندی نامحدود.

ادامه

یافتن میانه بدون مرتب‌سازی کامل: الگوریتم‌های انتخاب زمان-خطی

یافتن k-امین کوچک‌ترین عنصر در یک آرایه مرتب‌نشده نیازمند هزینه کامل Θ(n log n) مرتب‌سازی نیست؛ می‌تواند در زمان خطی انجام شود. این راهنمای جامع مورد بدیهی یافتن حداقل یا حداکثر، یک الگوریتم انتخاب تصادفی ظریف با زمان مورد انتظار خطی، و یک الگوریتم قطعی پیچیده‌تر که زمان خطی را حتی در بدترین‌حالت تضمین می‌کند را پوشش می‌دهد.

ادامه

شکستن مانع n log n: توضیح الگوریتم‌های مرتب‌سازی زمان-خطی

هر الگوریتم مرتب‌سازی مبتنی بر مقایسه در بدترین‌حالت حداقل به زمان Ω(n log n) نیاز دارد، اما الگوریتم‌هایی که کاملاً از مقایسه اجتناب می‌کنند می‌توانند تحت شرایط درست در زمان خطی مرتب کنند. این راهنمای جامع کران پایین مرتب‌سازی مبتنی‌بر‌مقایسه را با استدلال درخت تصمیم اثبات می‌کند، سپس سه الگوریتم زمان-خطی — counting sort، radix sort، و bucket sort — را همراه با فرضیات ورودی خاصی که هرکدام نیاز دارند توضیح می‌دهد.

ادامه

Quicksort: راهنمای کامل توصیف، کارایی، و تصادفی‌سازی

Quicksort یکی از پراستفاده‌ترین الگوریتم‌های مرتب‌سازی در عمل است، که به‌خاطر کارایی عالی حالت‌میانگین و عملیات درجا ارزشمند است، با وجود داشتن بدترین‌حالت نظری ضعیف. این راهنمای جامع الگوریتم مبتنی بر partition را با جزئیات پوشش می‌دهد، هم زمان اجرای بدترین‌حالت و هم مورد انتظار آن را تحلیل می‌کند، و توضیح می‌دهد تصادفی‌سازی چگونه آن را به یک الگوریتم به‌طور قابل‌اعتماد کارآمد صرف‌نظر از ترتیب ورودی تبدیل می‌کند.

ادامه

Heapsort و صف‌های اولویت: راهنمای کامل هیپ دودویی

هیپ دودویی یکی از ظریف‌ترین ساختارهای داده در علوم کامپیوتر است، که هم یک الگوریتم مرتب‌سازی کارآمد درجا و هم انتزاع صف اولویت مورد استفاده در سراسر طراحی الگوریتم را ممکن می‌سازد. این راهنمای جامع ویژگی‌های هیپ و نمایش آرایه‌ای، عملیات اصلی heapify، ساخت یک هیپ از یک آرایه مرتب‌نشده، الگوریتم کامل heapsort، و عملیات‌های صف اولویت ساخته‌شده روی هیپ‌ها را پوشش می‌دهد.

ادامه

<h2>Why Randomness Enters Algorithm Analysis</h2> <p>The worst-case, best-case, and average-case running times discussed earlier in this series all assume the algorithm itself behaves deterministically, and any variation comes purely from the input. A different situation arises when either the input distribution is unknown or an algorithm deliberately makes random choices during its own execution. Both situations require the tools of <code>Probabilistic Analysis</code>.</p> <h2>The Hiring Problem: A Motivating Example</h2> <p>Consider a company interviewing candidates one at a time for a position, always hiring the current best candidate seen so far and firing the previous hire. Each interview costs a small amount, but each hire costs significantly more, since it involves paperwork, onboarding, and severance for the person being replaced. The question is: what is the expected total hiring cost across the entire process?</p> <pre class="code-block"><code>HIRE-ASSISTANT(n): best = candidate 0 (a placeholder, ranked worst) for i = 1 to n: interview candidate i if candidate i is better than best: best = candidate i hire candidate i</code></pre><br> <p>If candidates arrive in the worst possible order — already sorted from worst to best — every single candidate is hired, resulting in <code>n</code> hires, a costly worst case. But if the order of candidates is random, far fewer hires are expected on average, since a random arrival order makes it unlikely that many consecutive candidates each set a new record.</p> <h2>Two Approaches to Handling the Order of Inputs</h2> <p>There are two distinct ways to reason about this randomness, and it is important not to confuse them.</p> <ul> <li><code>Probabilistic Analysis of a Deterministic Algorithm</code>: assume the input itself comes from some probability distribution (such as a uniformly random ordering of candidates), and analyze the expected running time of a fixed, non-random algorithm over that input distribution.</li> <li><code>Randomized Algorithms</code>: the algorithm itself makes random choices during execution (such as randomly shuffling the candidate order before processing them, regardless of the order they actually arrived in), guaranteeing good expected performance for any input, since the randomness comes from the algorithm rather than an assumption about the input.</li> </ul> <p>The second approach is generally more powerful and reliable in practice, since it removes any dependence on assumptions about how inputs are distributed in the real world, which may not hold. A <code>Randomized Algorithm</code> for the hiring problem simply permutes the candidates randomly before running the same procedure, guaranteeing the same good expected cost regardless of the input's original order.</p> <h2>Indicator Random Variables: A Powerful Analytical Tool</h2> <p>Computing an expected value directly can be complicated when many interacting events are involved. <code>Indicator Random Variables</code> provide an elegant technique that dramatically simplifies such calculations, especially when combined with the linearity of expectation.</p> <p>For an event <code>A</code>, define the indicator random variable:</p> <pre class="code-block"><code>I{A} = 1 if A occurs I{A} = 0 if A does not occur Key property: E[I{A}] = Pr{A}</code></pre><br> <p>The expected value of an indicator variable simply equals the probability of the event it indicates. This becomes powerful when combined with <code>Linearity of Expectation</code>, which states that the expected value of a sum of random variables equals the sum of their expected values, regardless of whether the variables are independent.</p> <pre class="code-block"><code>E[X1 + X2 + ... + Xn] = E[X1] + E[X2] + ... + E[Xn] This holds even when the Xi are NOT independent — a crucial and often surprising fact</code></pre><br> <h2>Applying Indicator Variables to the Hiring Problem</h2> <p>Let <code>Xi</code> be the indicator random variable for the event that candidate <code>i</code> is hired. The total number of hires is <code>X = X1 + X2 + ... + Xn</code>. By linearity of expectation:</p> <pre class="code-block"><code>E[X] = E[X1] + E[X2] + ... + E[Xn] = Σ Pr{candidate i is hired}</code></pre><br> <p>Candidate <code>i</code> is hired precisely when candidate <code>i</code> is the best among the first <code>i</code> candidates seen so far. If the candidates arrive in a uniformly random order, candidate <code>i</code> is equally likely to be the best, second-best, or any rank among the first <code>i</code> candidates, so:</p> <pre class="code-block"><code>Pr{candidate i is hired} = 1/i Therefore: E[X] = Σ (i=1 to n) 1/i = H(n) This is the Harmonic Series, and H(n) = Θ(ln n)</code></pre><br> <p>This remarkable result shows that, despite there being <code>n</code> candidates, the expected number of hires grows only logarithmically with <code>n</code>, a dramatic improvement over the worst-case scenario of <code>n</code> hires. This calculation, made simple through indicator variables, would be considerably more complex using direct probability calculations involving joint distributions.</p> <h2>Why This Technique Generalizes So Widely</h2> <p>The indicator random variable technique is not specific to the hiring problem; it is a general tool applicable whenever a quantity of interest can be expressed as a sum of simpler zero-or-one outcomes, even when those outcomes are correlated with each other. This makes it one of the most broadly useful techniques in the probabilistic analysis of algorithms, and it reappears throughout later topics in this series wherever expected running time needs to be computed.</p> <h2>Why Randomization Matters for Real-World Algorithm Design</h2> <p>Randomized algorithms are used throughout computer science specifically because they can guarantee good expected performance without needing any assumption about the distribution of real-world inputs, protecting against adversarial or unusually structured inputs that could otherwise trigger an algorithm's worst case. A prominent example, explored in depth later in this series, is randomized quicksort, where randomly shuffling the input before sorting protects against the specific input orderings that would otherwise trigger quicksort's quadratic worst case.</p>

برخی الگوریتم‌ها در حین اجرا انتخاب‌های تصادفی می‌کنند، و تحلیل رفتار مورد انتظارشان نیازمند جعبه‌ابزاری متفاوت از تحلیل بدترین‌حالت به‌تنهایی است. این راهنمای جامع تحلیل احتمالاتی را از طریق مسئله کلاسیک استخدام معرفی می‌کند، متغیرهای تصادفی نشانگر را به‌عنوان یک ابزار تحلیلی قدرتمند توضیح می‌دهد، و نشان می‌دهد تصادفی‌سازی چگونه می‌تواند کارایی مورد انتظار یک الگوریتم را بهبود بخشد.

ادامه