1 of 58

Polynomial Multiplication

in O(n log2n)

Meetup April 9, 2019

2 of 58

WHY

  • Elegant
  • Efficient
  • Succinct
  • Cool

3 of 58

4 of 58

What Is It

  • Rough measure of algorithm performance
  • Usually refers to time or memory required for an input of a certain size

5 of 58

O(n)

for i = 1 to n� if a > b� a += b

6 of 58

O(n2)

for i = 1 to n� for j = 1 to n� if a > b� a += b

7 of 58

O(n)

for i = 1 to n� if a < b� a += b��for i = 1 to n� if c < b� c += b

if c < d� c = sqrt(d)

8 of 58

O(n3)

for i = 1 to n� for j = 1 to n� for k = 1 to n� if c < b� c += b�

9 of 58

O(log2 n)

binarySearch(array, key, low, high): � middle = (low + high) / 2�� if array[middle] == key return middle

elif key < array[middle]� return binarySearch(array, key, low, middle - 1)

else� return binarySearch(array, key, middle + 1, high)

10 of 58

Binary Search

Find 3 in 1 2 3 4 5 6 7 8 9 10

1 2 3 4 5 6 7 8 9 10

1 2 3 4

3 4

�How many times can you halve n (down to 1)? log2n

11 of 58

Example Graphs

12 of 58

Timings

N = 100 takes 1 second

How long does it take for N = 10000 (100 times more)?

O(log2n) 2s

O(n) 100s

O(n2) 10,000s (2h:46)

O(n log2n) 200s

13 of 58

Properties

  • "Grows no faster than" (Upper bound)
  • For sufficiently large values
  • Up to a constant multiplier
    • O(100n) = O(n)
  • Fastest growth term only
    • O(n2+5n+1) = O(n2)

14 of 58

Divide

and

Conquer

15 of 58

Principle

  • Split problem into sub-problems
    • Smallest problems could be trivial to solve
  • Combine results if needed

16 of 58

Binary Search

binarySearch(array, key, low, high): � middle = (low + high) / 2�� if array[middle] == key � return middle

elif key < array[middle]� return binarySearch(array, key, low, middle - 1)

else� return binarySearch(array, key, middle + 1, high)

17 of 58

Merge Sort

mergeSort(array) first = mergeSort(array[0..n/2])� second = mergeSort(array[n/2..n])

result = []

while first.notEmpty or second.notEmpty� if first[0] < second[0]: smallest = first.removeAt(0)� else: smallest = second.removeAt(0)�� result.add(smallest)

return result

18 of 58

Merge Sort

O(n log2n)

Why:

  • max depth is log2n
  • at each level n items are merged in total

�Also in general:

T(n) = 2T(n/2) + O(n) gives O(n log2n)

19 of 58

John Von Neumann

  • Computing architecture
  • Linear programming
  • Game theory
  • Quantum physics + bomb
  • Mathematics

20 of 58

D&C - Because

  • Framework for approaching problems; simplifies work
  • When done right, reduces run-time

21 of 58

Polynomials

22 of 58

Polynomials

2x2 + 5x - 1

x3 - x + 2

anxn + an-1xn-1 + … + a0x0

n is the degree

23 of 58

Polynomial Representation

P as coefficients:

[a0, a1, a2, ..., an]

24 of 58

Multiplication

(2x2 + 5x - 1)(x3 - x + 2) =

2x5 - 2x3 + 4x2 +

5x4 - 5x2 + 10x -

x3 + x - 2

= 2x5 + 5x4 - x3 - x2 + 11x - 2

25 of 58

Multiplication Algorithm

r = [0, 0, ...]

for i = 0 to len(a)� for j = 0 to len(b)� r[i + j] += a[i] * b[j]

O(n2)

26 of 58

Alternative Representation

P as values at different points:

[x1, x2, ..., xn+1]

[P(x1), P(x2), ..., P(xn+1)]

27 of 58

Example

P(x) = x2 + 1�x in [0, 1, 2]

P(0) = 1�P(1) = 2�P(2) = 5

28 of 58

Multiplication

A(x) = x + 2 A(-1) = 1 A(0) = 2 A(1) = 3

B(x) = x - 1 B(-1) = -2 B(0) = -1 B(1) = 0

C(x) = x2 + x - 2 C(-1) = -2 C(0) = -2 C(1) = 0

O(n)

29 of 58

Conversion Between Representation

  • Evaluation
    • Given coefficients, compute values at different points
  • Interpolation
    • Given values at different points, compute coefficients
    • Lagrange formula

30 of 58

Idea

  • Evaluate A and B at 2n+1 points
  • Multiply the values - O(n)
  • Interpolate the result to get C

31 of 58

Idea

  • Evaluate A and B at 2n+1 points - O(n2)
  • Multiply the values - O(n)
  • Interpolate the result to get C - O(n2)

Need an Evaluate/Interpolate method faster than O(n2).

32 of 58

Implement Evaluate

We'll try to solve this using D&C.

Evaluate(a, x)

a = [a0, a1, ..., an]�x = [x0, x1, ...]

How to split the problem?

33 of 58

Odd & Even Terms

A [a0, a1, a2, a3, ...] a0 + a1x + a2x2 + a3x3 + ...

Aeven [a0, a2, a4, ...] a0 + a2y + a4y2 + ... �Aodd [a1, a3, a5, ...] a1 + a3y + a5y2 + ...

34 of 58

Odd & Even Terms

A [a0, a1, a2, a3, ...] a0 + a1x + a2x2 + a3x3 + ...

Aeven [a0, a2, a4, ...] a0 + a2y + a4y2 + ... �Aodd [a1, a3, a5, ...] a1 + a3y + a5y2 + ...

A(x) = Aeven(x2) + x * Aodd(x2)

�because

a0 + a2x2 + a4x4 + ... + xa1+ xa3x2 + xa5x4 + ...

35 of 58

Algorithm Attempt 1

Evaluate(a, x)� aeven = [a0, a2, a4, ...]� aodd = [a1, a3, a5, ...]� x2 = [x02, x12, x22, ...]

veven = Evaluate(aeven, x2)� vodd = Evaluate(aodd, x2)

for i = 0 to len(x)� v[i] = veven[i] + x[i] * vodd[i]

return v

36 of 58

Algorithm Attempt 1

Evaluate(a, x)� aeven = [a0, a2, a4, ...]� aodd = [a1, a3, a5, ...]� x2 = [x02, x12, x22, ...]

veven = Evaluate(aeven, x2)� vodd = Evaluate(aodd, x2)

for i = 0 to len(x)� v[i] = veven[i] + x[i] * vodd[i]

return v

O(n2)

37 of 58

Positive And Negative Points

x0, x1, x2, ..., xj, xj+1, xj+2, ...

Pick them such as:

x0 = -xj�x1 = -xj+1�x2 = -xj+2�...

38 of 58

Positive And Negative Points

x = 1, 2, 3, 4, ..., -1, -2, -3, -4

x2 = 1, 4, 9, 16, ..., 1, 4, 9, 16

39 of 58

Positive And Negative Points

x = 1, 2, 3, 4, ..., -1, -2, -3, -4

x2 = 1, 4, 9, 16, ..., 1, 4, 9, 16

also:�

A(x) = Aeven(x2) + x * Aodd(x2)

�A(-x) = Aeven(x2) - x * Aodd(x2)

40 of 58

Algorithm Attempt 2

Evaluate(a, x)� xhalf2 = [x02, x12, x22, ..., xj-12], j = len(x) / 2

veven = Evaluate(aeven, xhalf2)� vodd = Evaluate(aodd, xhalf2)

for i = 0 to j� v[i] = veven[i] + x[i] * vodd[i]� v[i + j] = veven[i] - x[i] * vodd[i]

return v

41 of 58

Algorithm Attempt 2

Evaluate(a, x)� xhalf2 = [x02, x12, x22, ..., xj-12]

veven = Evaluate(aeven, xhalf2)� vodd = Evaluate(aodd, xhalf2)

for i = 0 to j� v[i] = veven[i] + x[i] * vodd[i]� v[i + j] = veven[i] - x[i] * vodd[i]

return v

O(nlog2n)

42 of 58

Ideal Points

Two properties:

  • the first half are the opposites of the other half
    • 1, 2, 3, 4, -1, -2, -3, -4

  • the first property holds even after we square half of them
    • 1, 4, 9, 16��

Is this even possible?

43 of 58

Complex Numbers

44 of 58

Basics

0

-2 -1 1 2

2i

i

-i

-2i

45 of 58

Basics

a

b

z

z = a + bi

Ex:

2 + 3i

0

46 of 58

Polar Coordinates

θ

r

z

z = r cos θ + i r sin θ

Euler

z = r e

0

47 of 58

Polar Coordinates

θ=π

r=1

z = r cos θ + i r sin θ

Euler

z = r e

Famous formula

e = -1

0

-1

48 of 58

Power

θ=π/4

r=1

Multiplication

z1 = r1eiθ1

z2 = r2 eiθ2

z1 * z2 = (r1r2)ei(θ1+θ2)

Raise to power

zn = rneiθn

Ex:

(eiπ/4)2 = eiπ/2 = i

0

49 of 58

Unit Circle

0

1

Unit circle

All points with r = 1

50 of 58

Roots OF unity

0

1

zn = 1

z8 = 1 has 8 solutions

ω80, ω81, ω82, ω83,...

ω81 can simply be written ω8 since the others are just its powers

Property - half are opposites

51 of 58

Roots OF unity

0

1

Property - the squares of ω8 values are the ω4 values

52 of 58

Roots OF unity

0

1

Property - the squares of ω8 values are the ω4 values

n)2 = ωn/2

Property - half of these are still opposites

Bingo!

53 of 58

Wrapping Up

54 of 58

Evaluate

wd is the first d root of unity; d is the smallest power of 2 larger than the degree of a

Evaluate(a, wd)� if len(a) = 1 return a� veven = Evaluate(aeven, wd2)� vodd = Evaluate(aodd, wd2)

for i = 0 to j� v[i] = veven[i] + wdi * vodd[i]� v[i + j] = veven[i] - wdi * vodd[i]

return v

55 of 58

Interpolate

V = Evaluate(a, wd)

we can get a back simply doing

a = 1/d Evaluate(V, wdd-1)

56 of 58

Polynomial Multiplication

Multiply(a, b)

Va = Evaluate(a, wd)� Vb = Evaluate(b, wd)� � for i = 0 to len(Va)� Vc = Va[i] * Vb[i]� � c = 1/d * Evaluate(Vc, wdd-1)� return c

O(nlog2n)

57 of 58

Notes

  • Algorithm by Carl Friedrich Gauss (1805)
  • Rediscovered by Cooley-Tukey (1965)
  • "Evaluate" is actually FFT

58 of 58

References