\documentclass[10pt]{article}
\usepackage{fullpage}
\usepackage{amsmath,amsfonts,amsthm}
\usepackage[english]{babel}
\usepackage[capitalize, noabbrev]{cleveref}

% these are compressed lists to help fit into a 1 page limit
\newenvironment{enumerate*}%
  {\vspace{-2ex} \begin{enumerate} %
     \setlength{\itemsep}{-1ex} \setlength{\parsep}{0pt}}%
  {\end{enumerate}}
 
\newenvironment{itemize*}%
  {\vspace{-2ex} \begin{itemize} %
     \setlength{\itemsep}{-1ex} \setlength{\parsep}{0pt}}%
  {\end{itemize}}
 
\newenvironment{description*}%
  {\vspace{-2ex} \begin{description} %
     \setlength{\itemsep}{-1ex} \setlength{\parsep}{0pt}}%
  {\end{description}}

\DeclareMathOperator*{\E}{\mathbb{E}}
\let\Pr\relax
\DeclareMathOperator*{\Pr}{\mathbb{P}}

\newcommand{\inprod}[1]{\left\langle #1 \right\rangle}
\newcommand{\eqdef}{\mathbin{\stackrel{\rm def}{=}}}
\newcommand{\llbracket}{[\![}

\newtheorem{theorem}{Theorem}
\newtheorem{lemma}{Lemma}

\author{Thibaut Horel}
\title{CS 229r Problem Set 1 -- Solutions}

\begin{document}

\maketitle
\section*{Problem 1}

\paragraph{(a)} Statement (6) is wrong. The number of min pointers is not
necessarily equal to the number of elements. Indeed, inserting an element can
possibly require creating a min pointer in its cluster and recursively
inserting its cluster id into the summary, leading to more to than one min
pointer for this element.

\paragraph{(b)} See \textbf{(c)}.

\paragraph{(c)} Let us denote by $N(u)$ the number of min pointers created when
inserting an element in a $u$-vEB tree. We have two cases:

\begin{itemize*}
    \item either a cluster already exists for that element, and then you just
        have to recusrively insert it in the cluster. In this case: $N(u)
        = N(\sqrt{u})$
    \item or you need to create a new cluster for this element (which creates
        one min pointer) and recursively insert the cluster id in the summary.
        In this case: $N(u) = 1 + N(\sqrt{u})$.
\end{itemize*}
In both cases, we have $N(u) \leq 1 + N(\sqrt{u})$. Solving this recursion
gives $N(u) = O(\log\log u)$ number of min-pointers per element, which
in turns gives a space complexity of $O(n\log\log u)$ for a $u$-vEB tree.

\paragraph{(d)} We give a family of examples for $n=\log u$, namely $b(u)$, the
first $\log(u)$ powers of two ($b(u)\eqdef (2^{\log{u}-1},\ldots, 4, 2,1)$. Let
us denote by $S(u)$ the number of min pointers created when inserting $b(u)$ in
a $u$-vEB tree.

We note that when inserting the first $\frac{\log u}{2}$ elements of $b(u)$, we
will have to create one new cluster for each element and insert the cluster ids
in the summary. But these cluster ids are exactly $b(\sqrt{u})$. The number of
min pointers created during this phase is $S(\sqrt{u}) + \frac{\log u}{2}$.

Then, inserting the last $\frac{\log u}{2}$ elements of $b(u)$ will lead to
inserting $b(\sqrt{u})$ in a new cluster whose id is 0, the number of min
pointers created during this phase is $1 + S(\sqrt{u})$.

Overall the number of min pointers created follows the recursion:
\begin{displaymath}
    S(u) = 2S(\sqrt{u}) + 1 + \frac{\log u}{2}
\end{displaymath}
Solving it leads to $S(u) = \Omega(\log u\log\log u) = \Omega(n\log\log u)$.
Since the space complexity of a $u$-vEB tree is equal to the number of min
pointers it contains, we have that the space complexity of the $u$-vEB tree
containing $b(u)$ is $\Omega(n\log\log u)$.

\paragraph{(e)} We can use indirection to achieve linear space complexity as
follows:
\begin{enumerate*}
    \item order the $n$ elements and organize them in $\frac{n}{\log u}$
        buckets of $\log u$ consecutive elements.
    \item for each bucket, create a balanced binary search tree (a sorted
        array is enough in the static case) containing its elements.
    \item create a $u$-vEB tree containing $\frac{n}{\log u}$ elements: the
        minimum element of each bucket. Each of them pointing to its associated
        bucket.
\end{enumerate*}

We can then answer a predecessor query by:
\begin{enumerate*}
    \item finding the right bucket by doing a predecessor query in the $u$-vEB
        tree in time $O\left(\log\log\left(\frac{n}{\log u}\right)\right)$.
    \item finding the predecessor in this bucket (either using the
        binary search structure, or doing a binary search in the case of
        a sorted array) in time $O(\log\log u)$ since the bucket only contains
        $\log u$ elements.
\end{enumerate*}

Since $n\leq u$, the overall time complexity is $O(\log\log u)$. The space
complexity is $O\left(\frac{n}{\log u}\log\log u\right)$ for the $u$-vEB tree
and $O(n)$ for the binary search trees, which is $O(n)$ overall.

\section*{Problem 2}

Let us define:
\begin{displaymath}
    m\eqdef \sum_{j=1}^{\sqrt{w}} 2^{m_j} \quad\text{with}\quad
    m_j\eqdef w-j\sqrt{w} + j.
\end{displaymath}
We have:
\begin{equation}\label{eq:dec}
    y\eqdef\left(\sum_{i=1}^{\sqrt{w}} x_i 2^{i\sqrt{w}-1}\right)\times m
    = \sum_{i=1}^{\sqrt{w}}\sum_{j=1}^{\sqrt{w}} x_i 2^{m_j+i\sqrt{w} -1}
\end{equation}

\begin{lemma}\label{lemma:oto}
    The function $(i,j) \mapsto m_j + i\sqrt{w} -1$ defined on
    $\{1,\ldots,\sqrt{w}\}^2$ is one-to-one.
\end{lemma}

\begin{proof}
    Let us assume that $m_j + i\sqrt{w} - 1 = m_l + k\sqrt{w} - 1$ for
    $(i,j,k,l)\in\{1,\ldots,\sqrt{w}\}^4$. Then using the definiton of $m_j$
    and $m_l$, we have:
    \begin{displaymath}
        \big[(i-j) - (k-l)\big]\sqrt{w} = l-j.
    \end{displaymath}
    Since $1-\sqrt{w}\leq l-j\leq \sqrt{w}-1$, this implies that $l-j = 0$ and
    $(i-j) - (k-l) = 0$. This in turn implies that $i=k$ and $l=j$.
\end{proof}

\cref{lemma:oto} allows us to interpret \cref{eq:dec} as the base
2 decomposition of $y$ (since all the exponents are distinct). Furthermore, for
  $i=j$, $m_i + i\sqrt{w} = w+i-1$, which shows that the bits between position
  $w$ and $w+\sqrt{w}-1$ will contain the bits of $x$ in consecutive order.
  Then, we simply shift $y$ by $w$ to the right ($t=w$) and keep the rightmost
  $\sqrt{w}$ bits (by masking) to obtain what we want. To summarize:

\begin{displaymath}
    \boxed{
    m= \sum_{j=1}^{\sqrt{w}} 2^{w-j\sqrt{w}+j} \quad\text{and}\quad
t = w}
\end{displaymath}

\section*{Problem 3}

\paragraph{Second solution.}
Using Problem 2 and what we did in class, we assume that we have access to the
following procedures:
\begin{itemize*}
    \item \texttt{perfect-sketch}: takes a word $x$ of length $w$ whose bits
        are all $0$ except possibly the ones at position $i\sqrt{w}-1$, $1\leq
        i\leq\sqrt{w}$ and compress them (preserving their order) to positions
        $0$ to $\sqrt{w}-1$. This is achieved using Problem 2.
        \begin{center}
            \texttt{perfect-sketch(x) := ((x * m) >> w) \& (1 << $\sqrt{\texttt{w}}$ - 1)}
        \end{center}
    \item \texttt{count-ones}: takes a word of length $w$ whose bits are all
        $0$ except possibly the ones at position $i\sqrt{w} -1$, $1\leq i\leq
        \sqrt{w}$ and counts the number of ones in this word. This is achieved
        by multiplying $x$ by $a\eqdef\sum_{j=0}^{\sqrt{w}-1}2^{j\sqrt{w}}$.
        The number of ones can be read between positions $w-1$ and $\sqrt{w}+w
        -2$ which can be extracted by shifting by $w-1$ to the right and
        masking to keep only the rightmost $\sqrt{w}$ bits.
        \begin{center}
            \texttt{count-ones(x) := ((x * a) >> (w - 1)) \& (1 << $\sqrt{\texttt{w}}$ - 1)}
        \end{center}
    \item \texttt{non-empty-clusters}: takes a word $x$ of length $w$ seen as
        the concatenation of $\sqrt{w}$ clusters of length $\sqrt{w}$ and
        returns a word of length $w$ which is the concatenation of clusters of
        length $\sqrt{w}$, each cluster being all zero, except for the leading
        bit indicating whether of not the corresponding cluster in $x$ is
        non-zero. This is achieved by defining $b\eqdef\sum_{j=1}^{\sqrt{w}}
        2^{j\sqrt{w}-1}$ and computing:
        \begin{center}
            \texttt{non-empty-clusters(x) := (x \& b) | ( b $\wedge$ ( b \& ( b - ( x \& $\sim$b)))) }
        \end{center}

    \item \texttt{repeat}: takes a word $x$ of length $\sqrt{w}$ and returns a word
        of length $w$ obtained by concatenating $x$ to itself $\sqrt{w}$ times:
        \begin{center}
            \texttt{repeat(x) := (x * a)}
        \end{center}
\end{itemize*}
    
Finally, we will need one last constant, $c$ which is the concatenation of
$\sqrt{w}$ blocks of length $\sqrt{w}$, the $k$-th rightmost block being equal
to $2^k-1$:
\begin{displaymath}
c\eqdef \sum_{k=1}^{\sqrt{w}} (2^k-1})2^{(k-1)\sqrt{w}}.
\end{displaymath} 

We note that if $x$ is a word of length $\sqrt{w}$, \texttt{repeat(x) \& c}
will consist of $\sqrt{w}$ clusters of length $\sqrt{w}$; the $k$-th rightmost
cluster is empty if the rightmost $k$ bits of $x$ are all zero, that is, if the
least significant bit of $x$ set to one is greater than or equal to $k$. Hence,
the least significant bit of $x$ set to one is equal to the number of empty
clusters in \texttt{repeat(x) \& c} which we can easily compute using the
\texttt{non-empty-clusters} procedure. This allows us to define a procedure
\texttt{lsb-short} which takes a word $x$ of length $\sqrt{w}$ and computes its
least significant bit set to one:
\begin{center}
    \texttt{lsb-short(x) := count-ones(b $\wedge$ non-empty-clusters(repeat(x) \& c))}
\end{center}

Then, the least significant bit set to one of a word $x$ of length $w$ can be
computed by first finding the rightmost non-empty cluster of length $\sqrt{w}$
in $x$, then extracting this cluster by shifting and masking, and then finding
the least significant bit set to one in this cluster:

\vspace{1em}

\noindent\texttt{def lsb(x):}\newline
\hspace*{1cm}\texttt{z := lsb-short(perfect-sketch(non-empty-clusters(x)))}\newline
\hspace*{1cm}\texttt{if z == $\sqrt{\texttt{w}}$:}\newline
\hspace*{2cm}\texttt{return -1}\newline
\hspace*{1cm}\texttt{else:}\newline
\hspace*{2cm}\texttt{return z * $\sqrt{\texttt{w}}$
+ lsb-short((x >> z * $\sqrt{\texttt{w}}$) \& (1 << $\sqrt{\texttt{w}}$ - 1))}

\vspace{1em}

Note that the above code only requires a constant number of multiplications and
bitwise operations once the constants $m$, $a$, $b$ and $c$ have been
pre-computed.

\paragraph{Alternative solution \emph{(too easy, felt like cheating).}} We saw in
class how to compute the most signigicant bit set to one. But observe that
\texttt{x \& $\sim$(x-1)} will clear all the bits of $x$ except for the least
significant bit set to one.  Assuming access to a procedure \texttt{msb} to
compute the most significant bit set to one, we can simply define
\texttt{lsb(x) $:=$ msb(x \& $\sim$(x-1))}.

\end{document}
