AlgoVerse

ضرب چندجمله‌ای‌ها با FFT

دو چندجمله‌ای را در O(n log n) ضرب می‌کند: هر دو را در ریشه‌های واحد ارزیابی می‌کند، مقدارها را نقطه به نقطه ضرب می‌کند و با FFT وارون ضریب‌ها را برمی‌گرداند.

ضرب مستقیم دو چندجمله‌ای درجه‌ی n (هر ضریب در هر ضریب) O(n²) است. ولی چندجمله‌ای را می‌شود با مقدارهایش در n نقطه هم نشان داد، و در این نمایش ضرب فقط O(n) است: مقدارها را نقطه به نقطه ضرب کن.

ادامه‌ی توضیح ↓
ورودی:
A 1×3 · B 1×2خروجی PDF

(1 + 2x + 3x²)(4 + 5x) = 4 + 13x + 22x² + 15x³؛ ضریب‌ها از توان صفر شروع می‌شوند.

  1. import cmath
  2. def multiply(A, B):
  3. # Coefficients, lowest power first: [a_0, a_1, …].
  4. a, b = A[0], B[0]
  5. size = len(a) + len(b) - 1
  6. n = 1
  7. while n < size:
  8. n = n * 2
  9. fa = fft(a + [0] * (n - len(a)), False)
  10. fb = fft(b + [0] * (n - len(b)), False)
  11. fc = [x * y for x, y in zip(fa, fb)]
  12. c = fft(fc, True)
  13. product = [round((v / n).real) for v in c][:size]
  14. return product
  15. def fft(a, inverse):
  16. n = len(a)
  17. if n == 1:
  18. return [complex(a[0])]
  19. sign = -1 if inverse else 1
  20. w_n = cmath.exp(sign * 2j * cmath.pi / n)
  21. even = fft(a[0::2], inverse)
  22. odd = fft(a[1::2], inverse)
  23. y = [0] * n
  24. w = 1
  25. for k in range(n // 2):
  26. t = w * odd[k]
  27. y[k] = even[k] + t
  28. y[k + n // 2] = even[k] - t
  29. w = w * w_n
  30. return y

ناوردا: (A·B)(x) = A(x)·B(x) در هر نقطه؛ پس مقدارهای حاصل‌ضرب در n نقطه، و از روی آن‌ها ضریب‌هایش، معلوم‌اند.

شروع اجرا

n—
product—

A

123

B

45

درخت فراخوانی‌های بازگشتی

نارنجی پر = فراخوانی در حال اجرا · حاشیه‌ی نارنجی = هنوز روی پشته · خاکستری = تمام شده

متغیرهای محلی

نارنجی = در همین گام عوض شد

A list

[1, 2, 3]

B list

[4, 5]

Call stack

  1. multiply()خط 4
گام ۱ از ۲۲۲
خط سیاه = pointwise · خط نارنجی = گام کلیدیevaluate: 0/1 · pointwise: 0/1 · interpolate: 0/1
    توضیح

    ایده

    ضرب مستقیم دو چندجمله‌ای درجه‌ی n (هر ضریب در هر ضریب) O(n²) است. ولی چندجمله‌ای را می‌شود با مقدارهایش در n نقطه هم نشان داد، و در این نمایش ضرب فقط O(n) است: مقدارها را نقطه به نقطه ضرب کن.

    سه گام

    1. ارزیابی: هر دو چندجمله‌ای را با FFT در n ریشه‌ی واحد حساب کن (n توان ۲ای که برای حاصل‌ضرب کافی است): O(n log n).
    2. ضرب نقطه‌ای: O(n).
    3. درون‌یابی: با FFT وارون ضریب‌های حاصل‌ضرب را برگردان: O(n log n).

    جمعاً O(n log n). چون عددهای میانی مختلط‌اند، ضریب‌های نهایی را به نزدیک‌ترین عدد صحیح گرد می‌کنیم.

    در trace به چه چیزی نگاه کنی

    • درخت فراخوانی سه FFT را نشان می‌دهد؛ product ضریب‌های نهایی از توان صفر به بالاست.