Running Time:
for i=1 to n do
for j=1 to n do
C[i,j] = 0
for k=1 to n do
C[i,j] = C[i,j] + A[i,k] + B[k,j]
endfor
endfor
endfor
IDEA: Divide the matrix into matrix of submatrices.
MATRIX-MULTIPLY(A, B)
// Assuming that both A and B are nxn matrices
if n == 1 then
return A * B
else
//partition A, B, and C as shown before
C[1,1] = MATRIX-MULTIPLY (A[1,1], B[1,1]) +
MATRIX-MULTIPLY (A[1,2], B[2,1]);
C[1,2] = MATRIX-MULTIPLY (A[1,1], B[1,2]) +
MATRIX-MULTIPLY (A[1,2], B[2,2]);
C[2,1] = MATRIX-MULTIPLY (A[2,1], B[1,1]) +
MATRIX-MULTIPLY (A[2,2], B[2,1]);
C[2,2] = MATRIX-MULTIPLY (A[2,1], B[1,2]) +
MATRIX-MULTIPLY (A[2,2], B[2,2]);
endif
return C
Case 1:
Similar with ordinary (iterative) algorithm.
Compute using recursive multiplications.
In normal case we need as below.
e.g. Show that :
Divide: Partition and into submatrices. Form terms to be multiplied using and .
Conquer: Perform multiplications of submatrices recursively.
Combine: Form using and on submatrices.
Recurrence:
Case 1:
so
The number may not seem much smaller than
But, it is significant because the difference is in the exponent.
Strassen’s algorithm beats the ordinary algorithm on today’s machines for or so.
Best to date: (of theoretical interest only)
For example, if the traditional algorithm taught in school multiplies a 4x5 by 5x5 matrix using 100 multiplications, and this number was reduced to 80 with human ingenuity, AlphaTensor has found algorithms that do the same operation using just 76 multiplications.
![center h:450px]
"Single-player game played by AlphaTensor, where the goal is to find a correct matrix multiplication algorithm. The state of the game is a cubic array of numbers (shown as grey for 0, blue for 1, and green for -1), representing the remaining work to be done."
Input: An array of values
Output: The contiguous subarray that has the largest sum of elements
Divide: Trivial (divide the array from the middle)
Conquer: Recursively compute the max subarrays of the left and right halves
Combine: Compute the max-subarray crossing the
TODO : detailed solution in textbook...
Key: Linear-time partitioning algorithm
Choose a pivot element
Rearrange the array such that:
Note: Everything in the left subarray ≤ everything in the right subarray
Note: Combine is trivial after conquer. Array already sorted.
H-PARTITION(A, p, r)
pivot = A[p]
i = p - 1
j = r - 1
while true do
repeat j = j - 1 until A[j] <= pivot
repeat i = i - 1 until A[i] <= pivot
if i < j then
exchange A[i] with A[j]
else
return j
H-PARTITION(A, p, r)
pivot = A[p]
i = p - 1
j = r - 1
while true do
repeat j = j - 1 until A[j] <= pivot
repeat i = i - 1 until A[i] <= pivot
if i < j then exchange A[i] with A[j]
else return j
QUICKSORT (A, p, r)
if p < r then
q = H-PARTITION(A, p, r)
QUICKSORT(A, p, q)
QUICKSORT(A, q + 1, r)
endif
Initial invocation: QUICKSORT(A,1,n)
QUICKSORT(A, p, q=r)
We need to prove claims to show correctness:
Notations:
Note: We always have and
because
Lemma 1: Either or at termination
Proof of Lemma 1:
The algorithm terminates when (the else condition).
So, it is sufficient to prove that
There are cases to consider:
By contradiction, assume there is a run with
Original correctness claims:
Proof:
The proof of claims (a) and (b) complete
Lemma 2: At the end of iteration , where (i.e. m is not the last iteration), we must have:
and
Proof of Lemma 2:
Ind. Hyp.: At the end of iteration , where (i.e. m is not the last iteration), we must have:
and
General case: The lemma holds for , where
Proof of base case complete!
Original correctness claim:
Proof of claim (c)
QUICKSORT (A, p, r)
if p < r then
q = L-PARTITION(A, p, r)
QUICKSORT(A, p, q - 1)
QUICKSORT(A, q + 1, r)
endif
Initial invocation: QUICKSORT(A,1,n)
of element comparisons:
of index comparisons:
of index increment/decrement operations:
Hoare’s algorithm is in general faster
Hoare behaves better when pivot is repeated in
QUICKSORT (A, p, r)
if p < r then
q = H-PARTITION(A, p, r)
QUICKSORT(A, p, q)
QUICKSORT(A, q + 1, r)
endif
Initial invocation: QUICKSORT(A,1,n)
Assume all elements are distinct in the following analysis
Partitioning always leads to parts of size and
(same as merge sort)
We have seen that if H-PARTITION always splits the array with ratio, the runtime will be .
Same is true with a split ratio of , etc.
Possible to show that if the split has always constant proportionality, then the runtime will be .
In other words, for a constant :
Reminder: H-PARTITION will place the pivot in the right partition unless the pivot is the smallest element in the arrays.
Question: If the pivot selected is the mth smallest value in the input array, what is the size of the left region after partitioning?
Question: What is the probability that the pivot selected is the smallest value in the array of size ?
Question: What is the probability that the left partition returned by H-PARTITION has size , where ?
The probability that H-PARTITION yields a split that is more balanced than is on a random array.
Let be the probability that H-PARTITION yields a split more balanced than , where
Repeat the analysis to generalize the previous result
Assumption: All permutations are equally likely
Unlikely: Splits always the same way at every level
Expectation:
Average case: A mix of good and bad splits
Compare 2-successive levels of avg case vs. 1 level of best case
In terms of the remaining subproblems, two levels of avg case is slightly better than the single level of the best case
The avg case has extra divide cost of at alternate levels
The extra divide cost of bad splits absorbed into the of good splits.
Running time is still
for any constant
For a random input array, the probability of having a split
for any constant
Avg case intuition: Different splits expected at different levels
Avg case intuition: Assume the good and bad splits alternate
R-QUICKSORT(A, p, r)
if p < r then
q = R-PARTITION(A, p, r)
R-QUICKSORT(A, p, q)
R-QUICKSORT(A, q+1, r)
R-PARTITION(A, p, r)
s = RANDOM(p, r)
exchange A[p] with A[s]
return H-PARTITION(A, p, r)
R-QUICKSORT(A, p, r)
if p < r then
q = R-PARTITION(A, p, r)
R-QUICKSORT(A, p, q-1)
R-QUICKSORT(A, q+1, r)
R-PARTITION(A, p, r)
s = RANDOM(p, r)
exchange A[r] with A[s]
return L-PARTITION(A, p, r)
Assume all elements in are distinct
Let
i.e. is the number of array elements with value less than or equal to
The following analysis will be for Quicksort using Hoare’s partitioning algorithm.
Reminder: The pivot is selected randomly and exchanged with before calling H-PARTITION
Let be the random pivot chosen.
What is the probability that for ?
TODO: convert to image...S6_P9
TODO: convert to image...S6_P10
for each term appears twice once for and once for
Splitting summations: ignore ceilings for simplicity
Q.E.D.
ith order statistic: smallest element of a set of elements
minimum: first order statistic
maximum: order statistic
median: “halfway point” of the set
Selection problem: Select the smallest of elements
Naïve algorithm: Sort the input array ; then return
Can we do any better?
Randomized algorithm using divide and conquer
Similar to randomized quicksort
Expected runtime:
R-SELECT(A,p,r,i)
if p == r then
return A[p];
q = R-PARTITION(A, p, r)
k = q–p+1;
if i <= k then
return R-SELECT(A, p, q, i);
else
return R-SELECT(A, q+1, r, i-k);
Upper bound: Assume element always falls into the larger part.
Works fast: linear expected time
Excellent algorithm in practise
But, the worst case is very bad:
Blum, Floyd, Pratt, Rivest & Tarjan[1973] algorithms are runs in linear time in the worst case.
Generate a good pivot recursively
//return i-th element in set S with n elements
SELECT(S, n, i)
if n <= 5 then
SORT S and return the i-th element
DIVIDE S into ceil(n/5) groups
//first ceil(n/5) groups are of size 5, last group is of size n mod 5
FIND median set M={m , …, m_ceil(n/5)}
// m_j : median of j-th group
x = SELECT(M,ceil(n/5),floor((ceil(n/5)+1)/2))
PARTITION set S around the pivot x into L and R
if i <= |L| then
return SELECT(L, |L|, i)
else
return SELECT(R, n–|L|, i–|L|)
Step 1: Divide the input array into groups of size
Step 2: Compute the median of each group ()
Step 3: Compute the median of the median group
where
Let be the set of the medians computed:
The runtime of the recursive call:
Step 4: Partition the input array around the median-of-medians
Partition around
Claim: Partitioning around x is guaranteed to be well-balanced.
Step 5: Make a recursive call to one of the partitions
if i <= |L| then
return SELECT(L,|L|,i)
else
return SELECT(R,n-|L|,i-|L|)
//return i-th element in set S with n elements
SELECT(S, n, i)
if n <= 5 then
SORT S and return the i-th element
DIVIDE S into ceil(n/5) groups
//first ceil(n/5) groups are of size 5, last group is of size n mod 5
FIND median set M={m , …, m_ceil(n/5)}
// m_j : median of j-th group
x = SELECT(M,ceil(n/5),floor((ceil(n/5)+1)/2))
PARTITION set S around the pivot x into L and R
if i <= |L| then
return SELECT(L, |L|, i)
else
return SELECT(R, n–|L|, i–|L|)