\documentclass[11pt]{article}

%\setlength{\topmargin}{-.8in}  
% \setlength{\oddsidemargin}{0in}
% \setlength{\evensidemargin}{0in}
% \setlength{\textwidth}{6.5in}
% \setlength{\textheight}{9.5in}

\usepackage{graphicx}
\usepackage{fullpage}
\begin{document}

\title{{\bf Divide-and-conquer}\\
(CLRS 4.2)}
\date{}

\maketitle



It's a powerful technique for solving problems: 

\fbox{
\parbox{11cm}{{\bf Divide-and-Conquer (Input: Problem P)}
\\
\\ To Solve P:
\begin{enumerate}
\item {\em Divide} P into smaller problems $P_1,P_2$
\item {\em Conquer} by solving the (smaller) subproblems recursively.
\item {\em Combine} solutions to $P_1,P_2$ into solution for P.
\end{enumerate}
}
}



\section*{Matrix Multiplication}


Let $X$ and $Y$ be two $n\times n$ matrices

$X= \left\{ \begin{array}{llcl}
    x_{11} & x_{12} & \cdots & x_{1n} \\
    x_{21} & x_{22} & \cdots & x_{1n} \\
    x_{31} & x_{32} & \cdots & x_{1n} \\
    \cdots & \cdots & \cdots & \cdots \\
    x_{n1} & x_{n2} & \cdots & x_{nn} 
  \end{array}
\right\} $

We want to compute $Z = X \cdot Y$, where $z_{ij} = \sum_{k=1}^n X_{ik} \cdot Y_{kj}$

Problem: Given two matrices of size $n$ by $n$, come up with an
algorithm to compute the product.


\begin{itemize}
\item The straightfoward method uses $\Rightarrow n^2 \cdot n = \Theta(n^3)$ operations

\item Can we do better?  That is, is it possible to multiply two
  matrices faster than $\Theta(n^3)$?

\item This was an open problem for a long time... until Strassen came
  up with an algorithm in 1969.  The idea is to use
  divide-and-conquer.

\end{itemize} 

\subsection*{Matrix multiplication with divide-and-conquer} 

\begin{itemize} 
\item Let's imagine that $n$ is a power of two. We can view each
  matrix as consisting of 2x2=4 $n/2$-by-$n/2$ matrices.

  $X = \left\{ \begin{array}{cc}
      A & B \\
      C & D
    \end{array}
  \right\}$,    $Y = \left\{ \begin{array}{cc}
      E & F \\
      G & H
    \end{array}
  \right\}$


\item Then we see that  their product  $X \cdot Y$ can be written as: 


  $\left\{ \begin{array}{cc}
      A & B \\
      C & D
    \end{array}
  \right\}
  \cdot
  \left\{ \begin{array}{cc}
      E & F \\
      G & H
    \end{array}
  \right\}
  =
  \left\{ \begin{array}{cc}
      (A\cdot E + B\cdot G) & (A\cdot F + B\cdot H) \\
      (C\cdot E + D\cdot G) & (C\cdot F + D\cdot H)
    \end{array}
  \right\}$
  
\item  The above naturally leads to divide-and-conquer solution:
  \begin{itemize}
  \item Divide $X$ and $Y$ into $8$ sub-matrices $A$, $B$, $C$, $D, E, F, G, H$.
  \item Compute $8$ $n/2$-by-$n/2$ matrix multiplications recursively.
  \item Combine results (by doing $4$ matrix additions) and copy the
    results into $Z$.
  \end{itemize}

  
\item ANALYSIS: Running time of algorithm is given by $T(n) = 8T(n/2) +
  \Theta(n^2) \Rightarrow T(n) = \Theta(n^3)$

\item Cool idea, but not so cool result......since we already
  discussed a (simpler/naive) $O(n^3)$ algorithm!

\item Can we do better?
\end{itemize}




\subsection*{Strassen's divide-and-conquer}

\begin{itemize}
\item Strassen's algorithm is based on the following observation: 

The recurrence $$T(n) = 8T(n/2) + \Theta(n^2) \Rightarrow T(n) =
\Theta(n^3)$$


while the recurrence 

$$T(n) = 7T(n/2) + \Theta(n^2) \Rightarrow T(n) =
\Theta(n^{\lg 7})$$



\item Strassen foud a way to compute only 7 products of $n/2$-by-$n/2$ matrices

\item With same notation as before, we define the following 7
  $n/2$-by-$n/2$ matrices:

  

  \begin{eqnarray*}
  S_1 &=& (B - D) \cdot (G + H)\\
  S_2 &=& (A + D)\cdot(E + H)\\
  S_3 &=& (A - C)\cdot(E + F)\\
  S_4 &=& (A + B)\cdot H\\
  S_5 &=& A\cdot(F - H)\\
  S_6 &=& D\cdot(G - E)\\
  S_7 &=& (C + D) \cdot E\\
  \end{eqnarray*}

\item Strassen observed that we can write the product $Z$ as:
  
  $Z= \left\{ \begin{array}{cc}
      A & B \\
      C & D
    \end{array}
  \right\}
  \cdot
  \left\{ \begin{array}{cc}
      E & F \\
      G & H
    \end{array}
  \right\}
  =
  \left\{ \begin{array}{cc}
      (S_1+S_2-S_4+S_6) & (S_4+S_5) \\
      (S_6+S_7) & (S_2+S_3+S_5-S_7)
    \end{array}
  \right\}$
  
  
  
\item For e.g. let's test that $S_6 + S_7$ is really $C \cdot E + D \cdot G$
  \begin{eqnarray*}
    S_6 + S_7 & = & D\cdot (G-E) + (C+D)\cdot E \\
    & = & DG - DE + CE + DE \\
    & = & DG + CE
  \end{eqnarray*}
  
  
\item This leads to a divide-and-conquer algorithm:
  \begin{itemize}
  \item Divide $X$ and $Y$ into $8$ sub-matrices $A$, $B$, $C$, $D, E, F, G, H$.
  \item Compute $S_1, S_2, S_3, ..., S_7$. This involves 10 matrix additions
    and $7$ multiplications recursively.
  \item Compute $S_1+S_2 - S_4 + S_6$, ... and copy them in $Z$. This step involves only additions/subtractions of $n/2$-by-$n/2$ matrices. 
  \end{itemize}

\item ANALYSIS:  $T(n) = 7T(n/2) + \Theta(n^2)$, with solution $O(n^{\lg 7})$. 

\item Lets solve the recurrence using the iteration method
  
  \begin{eqnarray*}
    T(n) & = & 7T(n/2) + n^2 \\
    & = & n^2 + 7(7T(\frac{n}{2^2}) + (\frac{n}{2})^2) \\
    & = & n^2 + (\frac{7}{2^2})n^2 + 7^2T(\frac{n}{2^2}) \\
    & = &  n^2 + (\frac{7}{2^2})n^2 + 7^2(7T(\frac{n}{2^3}) +
    (\frac{n}{2^2})^2) \\ 
    & = & n^2 + (\frac{7}{2^2})n^2 + (\frac{7}{2^2})^2\cdot n^2 +
    7^3T(\frac{n}{2^3}) \\ 
    & = & n^2 + (\frac{7}{2^2})n^2 + (\frac{7}{2^2})^2n^2 +
    (\frac{7}{2^2})^3n^2 .... +  (\frac{7}{2^2})^{\log n -1}n^2 + 7^{\log n} \\
    & = & \sum_{i=0}^{\log n -1} (\frac{7}{2^2})^in^2 + 7^{\log n} \\
    & = & n^2\cdot\Theta((\frac{7}{2^2})^{\log n -1}) + 7^{\log n} \\
    & = & n^2\cdot\Theta(\frac{7^{\log n}}{(2^2)^{\log n}}) + 7^{\log n} \\
    & = & n^2\cdot\Theta(\frac{7^{\log n}}{n^2}) + 7^{\log n} \\
    & = & \Theta(7^{\log n}) \\
  \end{eqnarray*}
  
  \begin{itemize}
  \item Now we have the following:
    \begin{eqnarray*}
      7^{\log n} & = & 7^{\frac{\log_7 n}{\log_7 2}} \\
      & = & (7^{\log_7 n})^{(1/\log_7 2)} \\
      & = & n^{(1/\log_7 2)} \\
      & = & n^{\frac{\log_2 7}{\log_2 2}} \\
      & = & n^{\log 7}
    \end{eqnarray*}
    
 %% \item Or in general: $a^{\log_k n}=n^{\log_k a}$
  \end{itemize}
  

  So the solution is $T(n)=\Theta(n^{\lg 7})=\Theta(n^{2.81...})$
\end{itemize}

\begin{itemize}
\item Note:
  \begin{itemize}
  \item We are 'hiding' a much bigger constant in $\Theta()$ than before.
  \item Currently best known bound is $O(n^{2.376..})$ (Coppersmith and Winograd'78).
  \item Lower bound is (trivially) $ \Omega (n^2)$.
  \item Big open problem!!

  \item Strassen's algorithm has been found to be efficient in
    practice once $n$ is large enough.  For small values of $n$ the
    straightforward cubic algorithm is used instead. The crossover
    point where Strassen becomes more efficient depends from system to
    system.
  \end{itemize}
\end{itemize}


\end{document}

