From 1a63be358ec5e022232d1bcf453b8a567761c491 Mon Sep 17 00:00:00 2001 From: Douglas Rumbaugh Date: Tue, 24 Jun 2025 17:01:15 -0400 Subject: updates to background --- chapters/dynamization.tex | 787 ++++++++++++++++++++++++++++------------------ 1 file changed, 480 insertions(+), 307 deletions(-) (limited to 'chapters/dynamization.tex') diff --git a/chapters/dynamization.tex b/chapters/dynamization.tex index 12b3a2b..c89f1fa 100644 --- a/chapters/dynamization.tex +++ b/chapters/dynamization.tex @@ -102,7 +102,8 @@ are not all-inclusive, as there are a number of data structures which do not fit the classification, but such structures are outside of the scope of this work. -\subsubsection{Static Data Structures} +\begin{definition}[Static Data Structure~\cite{dsp}] +\label{def:static-ds} A static data structure does not support updates of any kind, but can be constructed from a data set and answer queries. Additionally, we @@ -116,12 +117,6 @@ data structures must support the following three operations, $F(\mathscr{I}, q)$ and returns the result. This operation runs in $\mathscr{Q}_S(n)$ time in the worst-case and \emph{cannot alter the state of $\mathscr{I}$}. - - In principle, a single data structure may be a solution to multiple - search problems. For example, B+trees can efficiently answer - point-lookup, set membership, and range scan. For our purposes, - however, we will be considering solutions to individual search - problems. \item $\mathbftt{build}:\left(\mathcal{PS}(\mathcal{D})\right) \to \mathcal{I}$ \\ $\mathbftt{build}(d)$ constructs a new instance of $\mathcal{I}$ @@ -136,6 +131,8 @@ data structures must support the following three operations, analysis. \end{itemize} +\end{definition} + Note that the term static is distinct from immutable. Static refers to the layout of records within the data structure, whereas immutable refers to the data stored within those records. This distinction will @@ -144,8 +141,8 @@ support to data structures. The data structures used are always static, but not necessarily immutable, because the records may contain header information (like visibility) that is updated in place. -\subsubsection{Half-dynamic Data Structures} - +\begin{definition}[Half-dynamic Data Structure~\cite{overmars-art-of-dyn}] +\label{def:half-dynamic-ds} A half-dynamic data structure requires the three operations of a static data structure, as well as the ability to efficiently insert new data into a structure built over an existing data set, $d$. @@ -158,16 +155,19 @@ a structure built over an existing data set, $d$. runs in $I(n)$ time in the worst-case. \end{itemize} -Note that the important aspect of insertion in this model is that the -effect of the new record on the query result is observed, not necessarily -that the result is a structure exactly identical to the one that would -be obtained by building a new structure over $d \cup r$. Also, though -the formalism used implies a functional operation where the original data +\end{definition} + +The important aspect of insertion in this model is that the effect of +the new record on the query result is observed, not necessarily that +the result is a structure exactly identical to the one that would be +obtained by building a new structure over $d \cup r$. Also, though the +formalism used implies a functional operation where the original data structure is unmodified, this is not actually a requirement. $\mathscr{I}$ could be sightly modified in place, and returned as $\mathscr{I}^\prime$, as is conventionally done with native dynamic data structures. -\subsubsection{Full-dynamic Data Structures} +\begin{definition}[Full-dynamic Data Structure~\cite{overmars-art-of-dyn}] +\label{def:full-dynamic-ds} A full-dynamic data structure is a half-dynamic structure that also has support for deleting records from the dataset. @@ -179,19 +179,20 @@ has support for deleting records from the dataset. runs in $D(n)$ time in the worst-case. \end{itemize} +\end{definition} + As with insertion, the important aspect of deletion is that the effect of $r$ on the results of queries answered using $\mathscr{I}^\prime$ has been removed, not necessarily that the record is physically removed from the structure. A full-dynamic data structure also -supports in-place modification of an existing record. In order to -update a record $r$ to $r^\prime$, it is sufficient to perform +supports in-place modification of an existing record. In order +to update a record $r$ to $r^\prime$, it is sufficient to perform $\mathbftt{insert}\left(\mathbftt{delete}\left(\mathscr{I}, r\right), r^\prime\right)$. -\subsubsection{Other Data Structures} There are data structures that do not fit into this classification scheme. For example, approximate structures like Bloom -filters~\cite{bloom70} or various sketchs and summaries, do not retain +filters~\cite{bloom70} or various sketches and summaries, do not retain full information about the records that have been used to construct them. Such structures cannot support \texttt{unbuild} as a result. Some other data structures cannot be statically queried--the act of querying them @@ -205,10 +206,10 @@ into a dynamic one. When certain conditions are satisfied by the data structure and its associated search problem, this process can be done automatically, and with provable asymptotic bounds on amortized insertion performance, as well as worst-case query performance. This automatic -approach is in constrast with the design of a native dynamic data +approach is in contrast with the design of a native dynamic data structure, which involves altering the data structure itself to natively support updates. This process usually involves implementing techniques -that partially rebuild small portions of the structure to accomodate new +that partially rebuild small portions of the structure to accommodate new records, which is called \emph{local reconstruction}~\cite{overmars83}. This is a very manual intervention that requires significant effort on the part of the data structure designer, whereas conventional dynamization @@ -255,11 +256,17 @@ It goes without saying that this operation is sub-optimal, as the insertion and deletion costs are both $\Theta(B(n))$, and $B(n) \in \Omega(n)$ at best for most data structures. However, this global reconstruction strategy can be used as a primitive for more sophisticated -techniques that can provide reasonable performance. +techniques that can provide reasonable performance. \begin{figure} - -\caption{\textbf{Data Structure Decomposition.} } +\centering +\includegraphics[width=.8\textwidth]{diag/decomp.pdf} +\caption{\textbf{Data Structure Decomposition.} A single large data +structure containing $n$ records can be decomposed into multiple instances +of the same data structure, each built over a disjoint partition of +the data. In this case, the decomposition is performed such that each +block contains $\sqrt{n}$ records. As a result, rather than an insert +requiring $B(n)$ time, it will require $B(\sqrt{n})$ time.} \label{fig:bg-decomp} \end{figure} @@ -274,18 +281,18 @@ devise decomposition schemes that result in asymptotic improvements of insertion performance when compared to global reconstruction alone. \begin{example}[Data Structure Decomposition] -Consider the sorted array data structure in Figure~\ref{fig:bg-decomp-1}, -where $|\mathscr{I}| = n$ and $B(n) \in \Theta(n \log n)$. Inserting a -new record into $\mathscr{I}$ will, then, require $\Theta(n \log n)$. -However, if the data structure is decomposed into blocks such that each -block has $\Theta(\sqrt{n})$ records, as shown in Figure~\ref{fig:bg-decomp-2}, -an insert only needs to rebuild one of the blocks, and thus the worst-case -cost of an insert becomes $\Theta(\sqrt{n} \log \sqrt{n})$. +Consider a data structure that can be constructed in $B(n) \in \Theta +(n \log n)$ time with $|\mathscr{I}| = n$. Inserting a new record into +this structure using global reconstruction will require $I(n) \in \Theta +(n \log n)$ time. However, if the data structure is decomposed into +blocks, such that each block contains $\Theta(\sqrt{n)})$ records, as shown +in Figure~\ref{fig:bg-decomp}, then only a single block must be reconstructed +to accommodate the insert, requiring $I(n) \in \Theta(\sqrt{n} \log \sqrt{n})$ time. \end{example} Much of the existing work on dynamization has considered different approaches to decomposing data structures, and the effects that these -approachs have on insertion and query performance. However, before we can +approaches have on insertion and query performance. However, before we can discuss these approaches, we must first address the problem of answering search problems over these decomposed structures. @@ -298,10 +305,9 @@ problem from the decomposition should be the same as would have been obtained had all of the data been stored in a single data structure. This requirement is formalized in the definition of a class of problems called \emph{decomposable search problems} (DSP). This class was first defined -by Bentley and Saxe in their work on dynamization, and we will adopt -their definition, +by Jon Bentley, -\begin{definition}[Decomposable Search Problem~\cite{saxe79}] +\begin{definition}[Decomposable Search Problem~\cite{dsp}] \label{def:dsp} A search problem $F: (\mathcal{D}, \mathcal{Q}) \to \mathcal{R}$ is decomposable if and only if there exists a constant-time computable, associative, and @@ -313,7 +319,7 @@ their definition, \end{definition} The requirement for $\mergeop$ to be constant-time was used by Bentley -and Saxe to prove specific performance bounds for answering queries from a +to prove specific performance bounds for answering queries from a decomposed data structure. However, it is not strictly \emph{necessary}, and later work by Overmars lifted this constraint and considered a more general class of search problems called \emph{$C(n)$-decomposable @@ -336,7 +342,9 @@ B, q) = F(A, q)~ \mergeop ~F(B, q)$. With these two results, induction demonstrates that the problem is decomposable even in cases with more than two partial results. -As an example, consider range scans, +As an example, consider the range counting problem, which seeks to +identify the number of elements in a set of 1-dimensional points that +fall onto a specified interval, \begin{definition}[Range Count] \label{def:range-count} Let $d$ be a set of $n$ points in $\mathbb{R}$. Given an interval, @@ -357,8 +365,8 @@ Definition~\ref{def:dsp}, gives \end{align*} which is true by the distributive property of union and intersection. Addition is an associative and commutative -operator that can be calculated in $\Theta(1)$ time. Therefore, range counts -are DSPs. +operator that can be calculated in $\Theta(1)$ time. Therefore, range count +is a decomposable search problem. \end{proof} Because the codomain of a DSP is not restricted, more complex output @@ -392,18 +400,34 @@ search problem can be answered over a decomposed structure by individually querying each block, and then merging the results together using $\mergeop$. In many cases, this process will introduce some overhead in the query cost. Given a decomposed data structure $\mathscr{I} -= \{\mathscr{I}_0, \mathscr{I}_1, \ldots, \mathscr{I}_m\}$, += \{\mathscr{I}_1, \mathscr{I}_2, \ldots, \mathscr{I}_m\}$, a query for a $C(n)$-decomposable search problem can be answered using, \begin{equation*} -\mathbftt{query}\left(\mathscr{I}, q\right) \triangleq \bigmergeop_{i=0}^{m} F(\mathscr{I}_i, q) +\mathbftt{query}\left(\mathscr{I}, q\right) \triangleq \bigmergeop_{i=1}^{m} F(\mathscr{I}_i, q) +\end{equation*} +which requires, +\begin{equation*} + \mathscr{Q}(n) \in O \left( m \cdot \left(\mathscr{Q}(n_\text{max}) + C(n)\right)\right) \end{equation*} -which requires $\mathscr{Q}_S(n) \in O\left(m \cdot ( -\mathscr{Q}(n_\text{max}) + C(n)\right)$ time, where $m$ is the number -of blocks and $n_\text{max}$ is the size of the largest block. Note -the fact that $C(n)$ is multiplied by $m$ in this expression--this is a -large part of the reason why $C(n)$-decomposability is not particularly -desirable compared to standard decomposability, where $C(n) \in \Theta(1)$ -and thus falls out of the cost function. +time, where $m$ is the number of blocks and $n_\text{max}$ is the size of the +largest block. Note the fact that $C(n)$ is multiplied by $m$ in this +expression--this is a large part of the reason why $C(n)$-decomposability +is not particularly desirable compared to standard decomposability, +where $C(n) \in \Theta(1)$ and thus falls out of the cost function. + +This is an upper bound only, it is occasionally possible to do +better. Under certain circumstances, the costs of querying multiple +blocks can be absorbed, resulting in no worst-case overhead, at least +asymptotically. As an example, consider a linear scan of the data running +in $\Theta(n)$ time. In this case, every record must be considered, +and so there isn't any performance penalty\footnote{ + From an asymptotic perspective. There will still be measurable + performance effects from caching, etc., even in this case. +} to breaking the records out into multiple chunks and scanning them +individually. More formally, for any query running in $\mathscr{Q}_S(n) \in +\Omega\left(n^\epsilon\right)$ time where $\epsilon > 0$, the worst-case +cost of answering a decomposable search problem from a decomposed +structure is $\Theta\left(\mathscr{Q}_S(n)\right)$.~\cite{saxe79} \section{Decomposition-based Dynamization for Half-dynamic Structures} @@ -420,120 +444,53 @@ this section, we will discuss these topics in the context of creating half-dynamic data structures, and the next section will discuss similar considerations for full-dynamic structures. -Of the decomposition techniques, we will focus on the two most important +Of the decomposition techniques, we will focus on the three most important from a practical standpoint.\footnote{ - There are, in effect, two main methods for decomposition. Other, - more complex, methods exist that consist of various compositions - of the two simpler ones. These more complex methods are of largely - theoretical interest, as they are complex enough to be of questionable - utility in practice.~\cite{overmars83} + There are, in effect, two main methods for decomposition: + decomposing based on some counting scheme (logarithmic and + $k$-binomial)~\cite{saxe79} or decomposing into equally sized blocks + (equal block method)~\cite{overmars-art-of-dyn}. Other, more complex, + methods do exist, but they are largely compositions of these two + simpler ones. These composed decompositions (heh) are of largely + theoretical interest, as they are sufficiently complex to be of + questionable practical utility.~\cite{overmars83} } The earliest of these is the logarithmic method, often called the Bentley-Saxe method in modern literature, and is the most commonly -discussed technique today. The Bentley-Saxe method has been directly +discussed technique today. The logarithmic method has been directly applied in a few instances in the literature, such as to metric indexing structures~\cite{naidan14} and spatial structures~\cite{bkdtree}, and has also been used in a modified form for genetic sequence search structures~\cite{almodaresi23} and graphs~\cite{lsmgraph}, to cite -a few examples. A later technique, the equal block method, was also -developed. It is generally not as effective as the Bentley-Saxe method, -and we have not identified any specific applications of this technique -outside of the theoretical literature, however we will discuss it as well -because it is simple, and lends itself well to demonstrating certain -useful properties of decomposition-based dynamization techniques that -we will take advantage of later. - - -\subsection{Equal Block Method} -\label{ssec:ebm} - -Though chronologically later, the equal block method is theoretically a -bit simpler, and so we will begin our discussion of decomposition-based -techniques for the dynamization of decomposable search problems -with it. There have been several proposed variations of this -concept~\cite{maurer79, maurer80}, but we will focus on the most developed -form as described by Overmars and von Leeuwen~\cite{overmars-art-of-dyn, -overmars83}. The core concept of the equal block method is to decompose -the data structure into a specified number of blocks, such that each -block is of roughly equal size. - -Consider a data structure $\mathscr{I} \in \mathcal{I}$ that solves -some decomposable search problem, $F$ and is built over a set of records -$d \in \mathcal{D}$. This structure can be decomposed into $s$ blocks, -$\mathscr{I}_1, \mathscr{I}_2, \ldots, \mathscr{I}_s$ each built over -partitions of $d$, $d_1, d_2, \ldots, d_s$. Fixing $s$ to a specific value -makes little sense when the number of records changes, and so it is taken -to be governed by a smooth, monotonically increasing function $f(n)$ such -that, at any point, the following two constraints are obeyed. -\begin{align} - f\left(\frac{n}{2}\right) \leq s \leq f(2n) \label{ebm-c1}\\ - \forall_{1 \leq j \leq s} \quad | \mathscr{I}_j | \leq \frac{2n}{s} \label{ebm-c2} -\end{align} -where $|\mathscr{I}_j|$ is the number of records in the block, -$|\text{unbuild}(\mathscr{I}_j)|$. - -A new record is inserted by finding the smallest block and rebuilding it -using the new record. If $k = \argmin_{1 \leq j \leq s}(|\mathscr{I}_j|)$, -then an insert is done by, -\begin{equation*} -\mathscr{I}_k^\prime = \text{build}(\text{unbuild}(\mathscr{I}_k) \cup \{r\}) -\end{equation*} -Following an insert, it is possible that Constraint~\ref{ebm-c1} is violated.\footnote{ - Constraint~\ref{ebm-c2} cannot be violated by inserts, but may be - violated by deletes. We're omitting deletes from the discussion at - this point, but will circle back to them in Section~\ref{ssec:dyn-deletes}. -} In this case, the constraints are enforced by "re-configuring" the -structure. $s$ is updated to be exactly $f(n)$, all of the existing -blocks are unbuilt, and then the records are redistributed evenly into -$s$ blocks. - -A query with parameters $q$ is answered by this structure by individually -querying the blocks, and merging the local results together with $\mergeop$, -\begin{equation*} -F(\mathscr{I}, q) = \bigmergeop_{j=1}^{s}F(\mathscr{I}_j, q) -\end{equation*} -where $F(\mathscr{I}, q)$ is a slight abuse of notation, referring to -answering the query over $d$ using the data structure $\mathscr{I}$. - -This technique provides better amortized performance bounds than global -reconstruction, at the possible cost of worse query performance for -sub-linear queries. We'll omit the details of the proof of performance -for brevity and streamline some of the original notation (full details -can be found in~\cite{overmars83}), but this technique ultimately -results in a data structure with the following performance characteristics, -\begin{align*} -\text{Amortized Insertion Cost:}&\quad I_A(n) \in \Theta\left(\frac{B(n)}{n} + B\left(\frac{n}{f(n)}\right)\right) \\ -\text{Worst-case Insertion Cost:}&\quad I(n) \in \Theta\left(B(n)\right) \\ -\text{Worst-case Query Cost:}& \quad \mathscr{Q}(n) \in \Theta\left(f(n) \cdot \mathscr{Q}_S\left(\frac{n}{f(n)}\right)\right) \\ -\end{align*} -where $B(n)$ is the cost of statically building $\mathcal{I}$, and -$\mathscr{Q}_S(n)$ is the cost of answering $F$ using $\mathcal{I}$. - -%TODO: example? - - -\subsection{The Bentley-Saxe Method} +a few examples. Bentley and Saxe also proposed a second approach, the +$k$-binomial method, that slightly alters the exact decomposition approach +used by the logarithmic method to allow for flexibility in whether the +performance of inserts or queries should be favored. A later technique, +the equal block method, was also developed, which also seeks to introduce +a mechanism for performance tuning. Of the three, the logarithmic method +is the most generally effective, and we have not identified any specific +applications of either $k$-binomial decomposition or the equal block method +outside of the theoretical literature. + +\subsection{The Logarithmic Method} \label{ssec:bsm} -%FIXME: switch this section (and maybe the previous?) over to being -% indexed at 0 instead of 1 - The original, and most frequently used, dynamization technique is the -Bentley-Saxe Method (BSM), also called the logarithmic method in older -literature. Rather than breaking the data structure into equally sized -blocks, BSM decomposes the structure into logarithmically many blocks -of exponentially increasing size. More specifically, the data structure -is decomposed into $h = \lceil \log_2 n \rceil$ blocks, $\mathscr{I}_1, -\mathscr{I}_2, \ldots, \mathscr{I}_h$. A given block $\mathscr{I}_i$ -will be either empty, or contain exactly $2^i$ records within it. +logarithmic method, also called Bentley-Saxe method (BSM) in more recent +literature. This technique decomposes the structure into logarithmically +many blocks of exponentially increasing size. More specifically, the +data structure is decomposed into $h = \lceil \log_2 n \rceil$ blocks, +$\mathscr{I}_1, \mathscr{I}_2, \ldots, \mathscr{I}_h$. A given block +$\mathscr{I}_i$ will be either empty, or contain exactly $2^i$ records +within it. The procedure for inserting a record, $r \in \mathcal{D}$, into -a BSM dynamization is as follows. If the block $\mathscr{I}_0$ -is empty, then $\mathscr{I}_0 = \text{build}{\{r\}}$. If it is not +a logarithmic decomposition is as follows. If the block $\mathscr{I}_1$ +is empty, then $\mathscr{I}_1 = \mathbftt{build}{\{r\}}$. If it is not empty, then there will exist a maximal sequence of non-empty blocks -$\mathscr{I}_0, \mathscr{I}_1, \ldots, \mathscr{I}_i$ for some $i \geq -0$, terminated by an empty block $\mathscr{I}_{i+1}$. In this case, -$\mathscr{I}_{i+1}$ is set to $\text{build}(\{r\} \cup \bigcup_{l=0}^i -\text{unbuild}(\mathscr{I}_l))$ and blocks $\mathscr{I}_0$ through +$\mathscr{I}_1, \mathscr{I}_1, \ldots, \mathscr{I}_i$ for some $i \geq +1$, terminated by an empty block $\mathscr{I}_{i+1}$. In this case, +$\mathscr{I}_{i+1}$ is set to $\mathbftt{build}(\{r\} \cup \bigcup_{l=1}^i +\mathbftt{unbuild}(\mathscr{I}_l))$ and blocks $\mathscr{I}_1$ through $\mathscr{I}_i$ are emptied. New empty blocks can be freely added to the end of the structure as needed. @@ -541,35 +498,43 @@ end of the structure as needed. \begin{figure} \centering \includegraphics[width=.8\textwidth]{diag/bsm.pdf} -\caption{An illustration of inserts into the Bentley-Saxe Method} +\caption{\textbf{Insertion in the Logarithmic Method.} A logarithmic +decomposition of some data structure initially containing records $r_1, +r_2, \ldots, r_{10}$ is shown, along with the insertion procedure. First, +the new record $r_{11}$ is inserted. The first empty block is at $i=1$, and +so the new record is simply placed there. Next, $r_{12}$ is inserted. For +this insert, the first empty block is at $i=3$, requiring the blocks $1$ +and $2$ to be merged, along with the $r_{12}$, to create the new block. +} \label{fig:bsm-example} \end{figure} Figure~\ref{fig:bsm-example} demonstrates this insertion procedure. The dynamization is built over a set of records $x_1, x_2, \ldots, -x_{10}$ initially, with eight records in $\mathscr{I}_3$ and two in -$\mathscr{I}_1$. The first new record, $x_{11}$, is inserted directly -into $\mathscr{I}_0$. For the next insert following this, $x_{12}$, the -first empty block is $\mathscr{I}_2$, and so the insert is performed by -doing $\mathscr{I}_2 = \text{build}\left(\{x_{12}\} \cup -\text{unbuild}(\mathscr{I}_1) \cup \text{unbuild}(\mathscr{I}_2)\right)$ -and then emptying $\mathscr{I}_1$ and $\mathscr{I}_2$. +x_{10}$ initially, with eight records in $\mathscr{I}_4$ and two in +$\mathscr{I}_2$. The first new record, $x_{11}$, is inserted directly +into $\mathscr{I}_1$. For the next insert following this, $x_{12}$, the +first empty block is $\mathscr{I}_3$, and so the insert is performed by +doing $\mathscr{I}_3 = \text{build}\left(\{x_{12}\} \cup +\text{unbuild}(\mathscr{I}_2) \cup \text{unbuild}(\mathscr{I}_3)\right)$ +and then emptying $\mathscr{I}_2$ and $\mathscr{I}_3$. This technique is called a \emph{binary decomposition} of the data -structure. Considering a BSM dynamization of a structure containing $n$ -records, labeling each block with a $0$ if it is empty and a $1$ if it -is full will result in the binary representation of $n$. For example, -the final state of the structure in Figure~\ref{fig:bsm-example} contains -$12$ records, and the labeling procedure will result in $0\text{b}1100$, -which is $12$ in binary. Inserts affect this representation of the -structure in the same way that incrementing the binary number by $1$ does. - -By applying BSM to a data structure, a dynamized structure can be created -with the following performance characteristics, +structure. Considering a logarithmic decomposition of a structure +containing $n$ records, labeling each block with a $0$ if it is empty and +a $1$ if it is full will result in the binary representation of $n$. For +example, the final state of the structure in Figure~\ref{fig:bsm-example} +contains $12$ records, and the labeling procedure will result +in $0\text{b}1100$, which is $12$ in binary. Inserts affect this +representation of the structure in the same way that incrementing the +binary number by $1$ does. + +By applying this method to a data structure, a dynamized structure can +be created with the following performance characteristics, \begin{align*} -\text{Amortized Insertion Cost:}&\quad I_A(n) \in \Theta\left(\left(\frac{B(n)}{n}\cdot \log_2 n\right)\right) \\ +\text{Amortized Insertion Cost:}&\quad I_A(n) \in \Theta\left(\frac{B(n)}{n}\cdot \log_2 n\right) \\ \text{Worst Case Insertion Cost:}&\quad I(n) \in \Theta\left(B(n)\right) \\ -\text{Worst-case Query Cost:}& \quad \mathscr{Q}(n) \in \Theta\left(\log_2 n\cdot \mathscr{Q}_S\left(n\right)\right) \\ +\text{Worst-case Query Cost:}& \quad \mathscr{Q}(n) \in O\left(\log_2 n\cdot \mathscr{Q}_S\left(n\right)\right) \\ \end{align*} This is a particularly attractive result because, for example, a data structure having $B(n) \in \Theta(n)$ will have an amortized insertion @@ -581,35 +546,230 @@ you consider the binary decomposition representation, the worst-case behavior is triggered each time the existing number overflows, and a new digit must be added. -As a final note about the query performance of this structure, because -the overhead due to querying the blocks is logarithmic, under certain -circumstances this cost can be absorbed, resulting in no effect on the -asymptotic worst-case query performance. As an example, consider a linear -scan of the data running in $\Theta(n)$ time. In this case, every record -must be considered, and so there isn't any performance penalty\footnote{ - From an asymptotic perspective. There will still be measurable performance - effects from caching, etc., even in this case. -} to breaking the records out into multiple chunks and scanning them -individually. For formally, for any query running in $\mathscr{Q}(n) \in -\Omega\left(n^\epsilon\right)$ time where $\epsilon > 0$, the worst-case -cost of answering a decomposable search problem from a BSM dynamization -is $\Theta\left(\mathscr{Q}(n)\right)$.~\cite{saxe79} +\subsection{The $k$-Binomial Method} + +\begin{figure} +\centering +\includegraphics[width=.8\textwidth]{diag/kbin.pdf} +\caption{\textbf{Insertion in the $k$-Binomial Method.} A $k$-binomial +decomposition of some data structure initially containing the records +$r_1 \ldots r_{18}$ with $k=3$, along with the values of the $D$ array. +When the record $r_{19}$ is inserted, $D[1]$ is incremented and, as it +is not equal to $D[2]$, no carrying is necessary. Thus, the new record is +simply placed in the structure at $i=1$. However, inserting the next record +will result in $D[1] = D[2]$ after the increment. Once this increment is +shifted, it will also be the case that $D[2] = D[3]$. As a result, the +entire structure is compacted into a single block. +} +\label{fig:dyn-kbin} +\end{figure} + +One of the significant limitations of the logarithmic method is that it +is incredibly rigid. In our earlier discussion of decomposition we noted +that there exists a clear trade-off between insert and query performance +for half-dynamic structures mediate by the number of blocks into which +the structure is decomposed. However, the logarithmic method does not +allow any navigation of this trade-off. In their original paper on the +topic, Bentley and Saxe proposed a different decomposition scheme that +does expose this trade-off, however, which they called the $k$-binomial +transform.~\cite{saxe79} + +In this transform, rather than decomposing the data structure based on +powers of two, the structure is decomposed based on a sum of $k$ binomial +coefficients. This decomposition results in exactly $k$ blocks in the +structure. For example, with $k=3$, the number 17 can be represented as, +\begin{align*} +17 &= {5 \choose 3} + {4 \choose 2} + {1 \choose 1} \\ +&= 10 + 6 + 1 +\end{align*} +and thus the decomposed structure will contain three blocks, one with +$10$ records, one with $6$, and another with $2$. + +More generally, a structure of $n$ elements is decomposed based on the +following sum of binary coefficients, +\begin{equation*} +n = \sum_{i=1}^{k} {D[i] \choose k} +\end{equation*} +where $D$ is an array of $k+1$ integers, such that $D[i] > D[i-1]$ +for all $i \leq k$, and $D[k+1] = \infty$. When a record is inserted, +$D[1]$ is incremented by one, and then this increment is ``shifted'' up +the array until no two adjacent integers are equal by considering each +element $i$ in the array and checking if it is equal to $i+1$. If it is, +the value at $D[i]$ is decremented and $D[i+1]$ incremented, and then $i$ +itself is incremented. This is guaranteed to terminate because the last +element of the array $D[k+1]$ is taken to be infinite. + +\begin{algorithm} +\caption{Insertion into a $k$-Binomial Decomposition} +\label{alg:dyn-binomial-insert} +\KwIn{$r$: the record to be inserted, $\mathscr{I} = \{ \mathscr{I}_1 \ldots \mathscr{I}_k\}$: a decomposed structure, $D$: the array of binomial coefficients} + +$D[1] \gets D[1] + 1$ \; +$S \gets \{r\} \cup \mathbftt{unbuild}(\mathscr{I}_1)$ \; +$\mathscr{I}_1 \gets \emptyset$ \; +\BlankLine +$i \gets 1$ \; +\While{$D[i] = D[i+1]$} { + $D[i+1] \gets D[i+1] + 1$ \; + $S \gets S \cup \mathbftt{unbuild}(\mathscr{I}_i)$ \; + \BlankLine + $D[i] \gets D[i] - 1$\; + $\mathscr{I}_i \gets \emptyset$\; + \BlankLine + $i \gets i + 1$\; +} +\BlankLine +$\mathscr{I}_i \gets \mathbftt{build}(S)$ \; + +\Return $\mathscr{I}$ +\end{algorithm} + +In order to maintain the structural decomposition based on those +results, the method maintains a list of $k$ structures, $\mathscr{I} = +\{\mathscr{I}_1 \ldots \mathscr{I}_k\}$ (which all start empty). During +an insert, a set of records to use to build the new block is initialized +with the record to be inserted. Then, each time $D[i]$ is considered +in the above increment algorithm, the structure $\mathscr{I}_i$ +is unbuilt and its records added to the set. When the increment +algorithm above terminates, a new block is built and placed at +$\mathscr{I}_i$. This process is a bit complicated, so we've summarized +it in Algorithm~\ref{alg:dyn-binomial-insert}. Figure~\ref{fig:dyn-kbin} +shows an example of inserting records into a $k$-binomial decomposition. + +Applying this technique results in the following costs for operations, +\begin{align*} +\text{Amortized Insertion Cost:}&\quad I_A(n) \in \Theta\left(\frac{B(n)}{n} \cdot \left(k! \cdot n\right)^{\frac{1}{k}}\right) \\ +\text{Worst-case Insertion Cost:}&\quad I(n) \in \Theta\left(B(n)\right) \\ +\text{Worst-case Query Cost:}& \quad \mathscr{Q}(n) \in O\left(k\cdot \mathscr{Q}_S(n)\right) \\ +\end{align*} + +Because the number of blocks is restricted to a constant, $k$, this method +is highly biased towards query performance, at the cost of insertion. +Bentley and Saxe also proposed a decomposition based on the dual of this +$k$-binomial approach. We won't go into the details here, but this dual +$k$-binomial method effectively reverses the insert and query trade-offs +to produce an insert optimized structure, with costs, + +\begin{align*} +\text{Amortized Insertion Cost:}&\quad I_A(n) \in \left( \frac{B(n)}{n} \cdot k\right) \\ +\text{Worst-case Insertion Cost:}&\quad I(n) \in \Theta\left(B(n)\right) \\ +\text{Worst-case Query Cost:}& \quad \mathscr{Q}(n) \in O\left(\left(k! \cdot n\right)^{\frac{1}{k}}\cdot \mathscr{Q}_S(n)\right) \\ +\end{align*} + +\subsection{Equal Block Method} +\label{ssec:ebm} + +\begin{figure} +\centering +\includegraphics[width=.8\textwidth]{diag/ebm.pdf} +\caption{\textbf{Insertion in the Equal Block Method.} An equal block +decomposition of some data structure initially containing the records +$r_1\ldots r_{14}$, with $f(n) = 3$. When the record $r_{15}$ is inserted, +the smallest block ($i=1$) is located, and the record is placed there +by rebuilding it. When the next record, $r_{16}$ is inserted, the value +of $f(n)$ increases to $4$. As a result, the entire structure must be +re-partitioned to evenly distribute the records over $4$ blocks during +this insert. +} +\label{fig:dyn-ebm} +\end{figure} + +The $k$-binomial method aims to provide the ability to adjust the +performance of a dynamized structure, selecting for either insert or +query performance. However, it is a bit of a blunt instrument, allowing +for a broadly insert-optimized system with horrible query performance, or +a broadly query-optimized system with horrible insert performance. Once +the system has been selected, the degree of trade-off can be slightly +adjusted by tweaking $k$. The desire to introduce a decomposition that +allowed for more fine-grained control over this trade-off resulted in a +third decomposition technique called the \emph{equal block method}. There +have been several proposed variations of this concept~\cite{maurer79, +maurer80}, but we will focus on the most developed form as described +by Overmars and von Leeuwen~\cite{overmars-art-of-dyn, overmars83}. The +core concept of the equal block method is to decompose the data structure +into a specified number of blocks, such that each block is of roughly +equal size. + +Consider an instance of a data structure $\mathscr{I} \in \mathcal{I}$ +that solves some decomposable search problem, $F$ and is built over +a set of records $d \in \mathcal{D}$. Rather than decomposing the data +structure based on some count-based scheme, as the two previous techniques +did, we can simply break the structure up into $s$ evenly sized blocks, +$\mathscr{I}_1, \mathscr{I}_2, \ldots, \mathscr{I}_s$ each built over +partitions of $d$, $d_1, d_2, \ldots, d_s$. Fixing $s$ to a constant +value results in large degradation of insert performance as the number +of records grows,\footnote{ + The $k$-binomial decomposition got away with fixed a constant number + of blocks because it scaled the sizes of the blocks to ensure that + there was a size distribution, and most of the reconstruction effort + occurred in the smaller blocks. When all the blocks are of equal size, + however, the cost of these reconstructions is much larger, and so it + becomes necessary to gradually grow the block count to ensure that + insertion cost doesn't grow too large. +} and so we instead take it to be governed by a smooth, monotonically +increasing function $f(n)$ such that, at any point, the following two +constraints are obeyed, +\begin{align} + f\left(\frac{n}{2}\right) \leq s \leq f(2n) \label{ebm-c1}\\ + \forall_{1 \leq j \leq s} \quad | \mathscr{I}_j | \leq \frac{2n}{s} \label{ebm-c2} +\end{align} + +A new record is inserted by finding the smallest block and rebuilding it +using the new record. If $k = \argmin_{1 \leq j \leq s}(|\mathscr{I}_j|)$, +then an insert is done by, +\begin{equation*} +\mathscr{I}_k^\prime = \mathbftt{build}(\mathbftt{unbuild}(\mathscr{I}_k) \cup \{r\}) +\end{equation*} +Following an insert, it is possible that Constraint~\ref{ebm-c1} is violated.\footnote{ + Constraint~\ref{ebm-c2} cannot be violated by inserts, but may be + violated by deletes. We're omitting deletes from the discussion at + this point, but will circle back to them in Section~\ref{ssec:dyn-deletes}. +} In this case, the constraints are enforced by re-configuring the +structure. $s$ is updated to be exactly $f(n)$, all of the existing +blocks are unbuilt, and then the records are redistributed evenly into +$s$ blocks. An example of insertion in the equal block method is shown +in Figure~\ref{fig:dyn-ebm}. + +This technique provides better amortized performance bounds than global +reconstruction, at the possible cost of worse query performance for +sub-linear queries. We'll omit the details of the proof of performance +for brevity and streamline some of the original notation (full details +can be found in~\cite{overmars83}), but this technique ultimately +results in a data structure with the following performance characteristics, +\begin{align*} +\text{Amortized Insertion Cost:}&\quad I_A(n) \in \Theta\left(\frac{B(n)}{n} + B\left(\frac{n}{f(n)}\right)\right) \\ +\text{Worst-case Insertion Cost:}&\quad I(n) \in \Theta\left(f(n)\cdot B\left(\frac{n}{f(n)}\right)\right) \\ +\text{Worst-case Query Cost:}& \quad \mathscr{Q}(n) \in O\left(f(n) \cdot \mathscr{Q}_S\left(\frac{n}{f(n)}\right)\right) \\ +\end{align*} +The equal block method is generally \emph{worse} in terms of insertion +performance than the logarithmic and $k$-binomial decompositions, because +the sizes of reconstructions are typically much larger for an equivalent +block count, due to all the blocks having approximately the same size. \subsection{Optimizations} +In addition to exploring various different approaches to decomposing the +data structure to be dynamized, the literature also explores a number of +techniques for optimizing performance under certain circumstances. In +this section, we will discuss the two most important of these for our +purposes: the exploitation of more efficient data structure merging, and +an approach for reducing the worst-case insertion cost of a decomposition +based loosely on the logarithmic method. + \subsubsection{Merge Decomposable Search Problems} -When a reconstruction is performed using these techniques, the inputs to -that reconstruction are not random collections of records, but rather -multiple data structures. While in the fully general case, these new -structures are built by first unbuilding all of the input structures and -then building a new one over that set of records, many data structures -admit more efficient \emph{merging}. Consider a data structure that -supports construction via merging, $\mathtt{merge}(\mathscr{I}_0, \ldots -\mathscr{I}_k)$ in $B_M(n, k)$ time, where $n = \sum_{i=0}^k -|\mathscr{I}_i|$. A search problem for which such a data structure exists is -called a \emph{merge decomposable search problem} (MDSP)~\cite{merge-dsp}. +When considering a decomposed structure, reconstructions are performed +not using a random assortment of records, but mostly using records +extracted from already existing data structures. In the case of static +data structures, as defined in Definition~\ref{def:static-ds}, the +best we can do is to unbuild the data structures and then rebuild from +scratch, there are many data structures which can be efficiently merged. +Consider a data structure that supports construction via merging, +$\mathbftt{merge}(\mathscr{I}_1, \ldots \mathscr{I}_k)$ in $B_M(n, k)$ +time, where $n = \sum_{i=1}^k |\mathscr{I}_i|$. A search problem for +which such a data structure exists is called a \emph{merge decomposable +search problem} (MDSP)~\cite{merge-dsp}. Note that in~\cite{merge-dsp}, Overmars considers a \emph{very} specific definition where the data structure is built in two stages. An initial @@ -633,23 +793,31 @@ built from an unsorted set of records. More formally, \begin{definition}[Merge Decomposable Search Problem~\cite{merge-dsp}] \label{def:mdsp} A search problem $F: (\mathcal{D}, \mathcal{Q}) \to \mathcal{R}$ - is decomposable if and only if there exists a data structure, - $\mathcal{I}$ capable of solving $F$ that is constructable by - merging $k$ instances of $\mathcal{I}$ with cost $B_M(n, k)$ such - that $B_M(n, \log n) \leq B(n)$. + is decomposable if and only if there exists a solution to the + search problem (i.e., a data structure) that is static, and also + supports the operation, + \begin{itemize} + \item $\mathbftt{merge}: \mathcal{I}^k \to \mathcal{I}$ \\ + $\mathbftt{merge}(\mathscr{I}_1, \ldots \mathscr{I}_k)$ returns a + static data structure, $\mathcal{I}^\prime$, constructed + from the input data structures, with cost $B_M(n, k) \leq B(n)$, + such that for any set of search parameters $q$, + \begin{equation*} + \mathbftt{query}(\mathscr{I}^\prime, q) = \mathbftt{query}(\mathbftt{build}(\mathbftt{unbuild}(\mathscr{I}_1)\cup\ldots\cup\mathbftt{unbuild}(\mathscr{I}_k))) + \end{equation*} + \end{itemize} \end{definition} -The use of $k = \log n$ in this definition comes from the Bentley-Saxe -method's upper limit on the number of data structures. In the worst case, -there will be $\log n$ structures to merge, and so to gain benefit -from the merge routine, the merging of $\log n$ structures must be -less expensive than building the new structure using the standard -$\mathtt{unbuild}$ and $\mathtt{build}$ mechanism. The availability of -an efficient merge operation isn't of much use in the equal block method, -which doesn't perform data structure merges, and so it isn't considered in -the above definition.\footnote{ +The value of $k$ can be upper-bounded by the decomposition technique +used. For example, in the logarithmic method there will be $\log n$ +structures to merge in the worst case, and so to gain benefit from the +merge routine, the merging of $\log n$ structures must be less expensive +than building the new structure using the standard $\mathtt{unbuild}$ +and $\mathtt{build}$ mechanism. Note that the availability of an efficient merge +operation isn't helpful in the equal block method, which doesn't +perform data structure merges.\footnote{ In the equal block method, all reconstructions are due to either - inserting a record or repartitioning of the records. In the former + inserting a record or re partitioning of the records. In the former case, the reconstruction pulls records from only a single structure and merging is not possible. In the latter, records may come from multiple structures, but the structures are not merged and only some @@ -657,26 +825,25 @@ the above definition.\footnote{ useful as an optimization. } -\subsubsection{Worst-Case Optimal Techniques} +\subsubsection{Improved Worst-Case Insertion Performance} \label{ssec:bsm-worst-optimal} Dynamization based upon amortized global reconstruction has a -significant gap between its \emph{amortized} insertion performance, -and its \emph{worst-case} insertion performance. When using the -Bentley-Saxe method, the logarithmic decomposition ensures that the -majority of inserts involve rebuilding only small data structures, -and thus are relatively fast. However, the worst-case insertion cost is -still $\Theta(B(n))$, no better than unamortized global reconstruction, -because the worst-case insert requires a reconstruction using all of -the records in the structure. +significant gap between its \emph{amortized} insertion performance, and +its \emph{worst-case} insertion performance. When using the Bentley-Saxe +method, the logarithmic decomposition ensures that the majority of inserts +involve rebuilding only small data structures, and thus are relatively +fast. However, the worst-case insertion cost is still $\Theta(B(n))$, +no better than global reconstruction, because the worst-case insert +requires a reconstruction using all of the records in the structure. Overmars and van Leeuwen~\cite{overmars81, overmars83} proposed an -alteration to the Bentley-Saxe method that is capable of bringing the +alteration to the logarithmic method that is capable of bringing the worst-case insertion cost in line with amortized, $I(n) \in \Theta \left(\frac{B(n)}{n} \log n\right)$. To accomplish this, they introduce a structure that is capable of spreading the work of reconstructions out across multiple inserts. Their structure consists of $\log_2 n$ -levels, like the Bentley-Saxe method, but each level contains four data +levels, like the logarithmic method, but each level contains four data structures, rather than one, called $Oldest_i$, $Older_i$, $Old_i$, $New_i$ respectively.\footnote{ We are here adopting nomenclature used by Erickson in his lecture @@ -703,61 +870,64 @@ on level $i$. This approach means that, in the worst case, partial reconstructions will be executed on every level in the structure, resulting in \begin{equation*} - I(n) \in \Theta\left(\sum_{i=0}^{\log_2 n-1} \frac{B(2^i)}{2^i}\right) \in \Theta\left(\log_2 n \frac{B(n)}{n}\right) + I(n) \in \Theta\left(\sum_{i=1}^{\log_2 n} \frac{B(2^i)}{2^i}\right) \in \Theta\left(\log_2 n \frac{B(n)}{n}\right) \end{equation*} time. Additionally, if $B(n) \in \Omega(n^{1 + \epsilon})$ for $\epsilon > 0$, then the bottom level dominates the reconstruction cost, and the -worst-case bound drops to $I(n) \in \Theta(\frac{B(n)}{n})$. +worst-case bound drops to $I(n) \in \Theta\left(\frac{B(n)}{n}\right)$. \section{Decomposition-based Dynamization for Full-dynamic Structures} \label{ssec:dyn-deletes} -Classical dynamization techniques have also been developed with -support for deleting records. In general, the same technique of global -reconstruction that was used for inserting records can also be used to -delete them. Given a record $r \in \mathcal{D}$ and a data structure -$\mathscr{I} \in \mathcal{I}$ such that $r \in \mathscr{I}$, $r$ can be -deleted from the structure in $C(n)$ time as follows, +Full-dynamic structures are those with support for deleting records, +as well as inserting. As it turns out, supporting deletes efficiently +is significantly more challenging than inserts, but there are some +results in the theoretical literature for efficient delete support in +restricted cases. + +While, as discussed earlier, it is in principle possible to support +deletes using global reconstruction, with the operation defined as \begin{equation*} -\mathscr{I}^\prime = \text{build}(\text{unbuild}(\mathscr{I}) - \{r\}) +\mathbftt{delete}(\mathscr{I}, r) \triangleq \mathbftt{build}(\mathbftt{unbuild}(\mathscr{I}) - \{r\}) \end{equation*} -However, supporting deletes within the dynamization schemes discussed -above is more complicated. The core problem is that inserts affect the -dynamized structure in a deterministic way, and as a result certain -partitioning schemes can be leveraged to reason about the -performance. But, deletes do not work like this. - -\begin{figure} -\caption{A Bentley-Saxe dynamization for the integers on the -interval $[1, 100]$.} -\label{fig:bsm-delete-example} -\end{figure} - -For example, consider a Bentley-Saxe dynamization that contains all -integers on the interval $[1, 100]$, inserted in that order, shown in -Figure~\ref{fig:bsm-delete-example}. We would like to delete all of the -records from this structure, one at a time, using global reconstruction. -This presents several problems, +the extension of this procedure to a decomposed data structure is less +than trivial. Unlike inserts, where the record can (in principle) be +placed into whatever block we like, deletes must be applied specifically +to the block containing the record. As a result, there must be a means to +locate the block containing a specified record before it can be deleted. +In addition to this, all three of the decomposition schemes discussed so +far take advantage of the fact that inserts can be applied to blocks in +a systematic manner to provide performance guarantees. Deletes, however, +lack this control, making bounding their performance far more difficult. + +For example, consider a logarithmic decomposition that contains all +integers on the interval $[1, 100]$, inserted in that order. We would +like to delete all of the records from this structure, one at a time, +using global reconstruction, in the opposite order they were inserted in. +Even if we assume that we can easily locate the block containing each +record to delete, we are still faced with two major problems, \begin{itemize} - \item For each record, we need to identify which block it is in before - we can delete it. \item The cost of performing a delete is a function of which block the - record is in, which is a question of distribution and not easily - controlled. + record is in, which is a question of distribution and not + easily controlled. In this example, we will always trigger + the worst-case behavior, repeatedly rebuilding the largest + blocks in the structure one at a time, as the number of + records diminishes. \item As records are deleted, the structure will potentially violate the invariants of the decomposition scheme used, which will require additional work to fix. \end{itemize} To resolve these difficulties, two very different approaches have been -proposed for supporting deletes, each of which rely on certain properties -of the search problem and data structure. These are the use of a ghost -structure and weak deletes. +proposed for creating full-dynamic structures. One approach requires the +search problem itself to have certain properties, and the other requires +certain operations to be supported by the data structure. We'll discuss +these next. \subsection{Ghost Structure for Invertible Search Problems} The first proposed mechanism for supporting deletes was discussed -alongside the Bentley-Saxe method in Bentley and Saxe's original +alongside the logarithmic method in Bentley and Saxe's original paper. This technique applies to a class of search problems called \emph{invertible} (also called \emph{decomposable counting problems} in later literature~\cite{overmars83}). Invertible search problems @@ -768,18 +938,18 @@ that is able to remove records from the result set. More formally, A decomposable search problem, $F$ is invertible if and only if there exists a constant time computable operator, $\Delta$, such that \begin{equation*} -F(A / B, q) = F(A, q)~\Delta~F(B, q) +F(A - B, q) = F(A, q)~\Delta~F(B, q) \end{equation*} for all $A, B \in \mathcal{PS}(\mathcal{D})$ where $A \cap B = \emptyset$. \end{definition} Given a search problem with this property, it is possible to emulate removing a record from the structure by instead inserting into a -secondary ``ghost'' structure. When the dynamization is queried, -this ghost structure is queried as well as the main one. The results -from the ghost structure can be removed from the result set using the -inverse merge operator. This simulates the result that would have been -obtained had the records been physically removed from the main structure. +secondary ``ghost'' structure. When the dynamization is queried, this +ghost structure is queried as well as the main one. The results from +the ghost structure can be removed from the result set using the inverse +merge operator. This simulates the result that would have been obtained +had the records been physically removed from the main structure. Two examples of invertible search problems are range count and set membership. Range count was formally defined in @@ -854,17 +1024,17 @@ supported with the same cost as an insert. Unfortunately, it suffers from write amplification because each deleted record is recorded twice--one in the main structure, and once in the ghost structure. This means that $n$ is, in effect, the total number of records and deletes. This can lead -to some serious problems, for example if every record in a structure -of $n$ records is deleted, the net result will be an "empty" dynamized +to some serious problems, for example if every record in a structure of +$n$ records is deleted, the net result will be an ``empty'' dynamized data structure containing $2n$ physical records within it. To circumvent this problem, Bentley and Saxe proposed a mechanism of setting a maximum threshold for the size of the ghost structure relative to the main one. Once this threshold was reached, a complete re-partitioning of the data -can be performed. During this re-paritioning, all deleted records can +can be performed. During this re-partitioning, all deleted records can be removed from the main structure, and the ghost structure emptied completely. Then all of the blocks can be rebuilt from the remaining records, partitioning them according to the strict binary decomposition -of the Bentley-Saxe method. +of the logarithmic method. \subsection{Weak Deletes for Deletion Decomposable Search Problems} @@ -939,7 +1109,7 @@ $\mathscr{Q}(n) \in \Theta(1)$ time and requires $\Omega(n)$ storage. Such a structure can support weak deletes. Each record within the structure has a single bit attached to it, indicating whether it has been deleted or not. These bits will require $\Theta(n)$ storage and -be initialized to 0 when the structure is constructed. A delete can +be initialized to $0$ when the structure is constructed. A delete can be performed by querying the structure for the record to be deleted in $\Theta(1)$ time, and setting the bit to 1 if the record is found. This operation has $D(n) \in \Theta(1)$ cost. @@ -953,19 +1123,19 @@ Definition~\ref{def:weak-delete} for weak deletes. Per Definition~\ref{def:weak-delete}, there must exist some constant dependent only on $\alpha$, $k_\alpha$, such that after $\alpha \cdot n$ deletes against $\mathscr{I}$ with $\alpha < 1$, the query cost is -bounded by $\Theta(\alpha \mathscr{Q}(n))$. +bounded by $\Theta(\alpha \cdot \mathscr{Q}(n))$. In this case, $\mathscr{Q}(n) \in \Theta(1)$, and therefore our final query cost must be bounded by $\Theta(k_\alpha)$. When a query is executed against $\mathscr{I}$, there are three possible cases, \begin{enumerate} \item The record being searched for does not exist in $\mathscr{I}$. In -this case, the query result is 0. +this case, the query result is $0$. \item The record being searched for does exist in $\mathscr{I}$ and has -a delete bit value of 0. In this case, the query result is 1. +a delete bit value of $0$. In this case, the query result is $1$. \item The record being searched for does exist in $\mathscr{I}$ and has -a delete bit value of 1 (i.e., it has been deleted). In this case, the -query result is 0. +a delete bit value of $1$ (i.e., it has been deleted). In this case, the +query result is $0$. \end{enumerate} In all three cases, the addition of deletes requires only $\Theta(1)$ extra work at most. Therefore, set membership over a static hash map @@ -1002,11 +1172,13 @@ drift away from the requirements imposed by the dynamization technique. It will eventually become necessary to re-partition the records to restore these invariants, which are necessary for bounding the number of blocks, and thereby the query performance. The particular invariant maintenance -rules depend upon the decomposition scheme used. +rules depend upon the decomposition scheme used. To our knowledge, +there is no discussion of applying the $k$-binomial method to deletion +decomposable search problems, and so method is not listed here. -\Paragraph{Bentley-Saxe Method.} When creating a BSM dynamization for +\Paragraph{Logarithmic Method.} When creating a logarithmic dynamization for a deletion decomposable search problem, the $i$th block where $i \geq 2$,\footnote{ - Block $i=0$ will only ever have one record, so no special maintenance must be + Block $i=1$ will only ever have one record, so no special maintenance must be done for it. A delete will simply empty it completely. } in the absence of deletes, will contain $2^{i-1} + 1$ records. When a @@ -1042,14 +1214,16 @@ limitations that prevent them from being directly usable as a general solution to the problem of creating database indices. Because of the requirement that the query being answered be decomposable, many search problems cannot be addressed--or at least efficiently addressed, by -decomposition-based dynamization. The techniques also do nothing to reduce -the worst-case insertion cost, resulting in extremely poor tail latency -performance relative to hand-built dynamic structures. Finally, these -approaches do not do a good job of exposing the underlying configuration -space to the user, meaning that the user can exert limited control on the -performance of the dynamized data structure. This section will discuss -these limitations, and the rest of the document will be dedicated to -proposing solutions to them. +decomposition-based dynamization. Additionally, though we have discussed +two decomposition approaches that expose some form of performance tuning +to the user, these techniques are targeted as asymptotic results, which +results in poor results in practice. Finally, most decomposition schemes +have poor worst-case insertion performance, resulting in extremely poor +tail latency relative to native dynamic structures. While there do exist +decomposition schemes that have exhibit better worst-case performance, +they are impractical. This section will discuss these limitations in +more detail, and the rest of the document will be dedicated to proposing +solutions to them. \subsection{Limits of Decomposability} \label{ssec:decomp-limits} @@ -1076,7 +1250,7 @@ range sampling are not decomposable. \subsubsection{k-Nearest Neighbor} \label{sssec-decomp-limits-knn} -The k-nearest neighbor (k-NN) problem is a generalization of the nearest +The k-nearest neighbor ($k$-NN) problem is a generalization of the nearest neighbor problem, which seeks to return the closest point within the dataset to a given query point. More formally, this can be defined as, \begin{definition}[Nearest Neighbor] @@ -1096,7 +1270,7 @@ In practice, it is common to require $f(x, y)$ be a metric,\footnote a metric space. Metric spaces require their distance functions to have the following properties, \begin{itemize} - \item The distance between a point and itself is always 0. + \item The distance between a point and itself is always $0$. \item All distances between non-equal points must be positive. \item For all points, $x, y \in D$, it is true that $f(x, y) = f(y, x)$. @@ -1139,9 +1313,9 @@ thought of as k-NN with $k=1$), this problem is \emph{not} decomposable. \begin{proof} To prove this, consider the query $KNN(D, q, k)$ against some partitioned -dataset $D = D_0 \cup D_1 \ldots \cup D_\ell$. If k-NN is decomposable, +dataset $D = D_1 \cup D_2 \ldots \cup D_\ell$. If k-NN is decomposable, then there must exist some constant-time, commutative, and associative -binary operator $\mergeop$, such that $R = \mergeop_{0 \leq i \leq l} +binary operator $\mergeop$, such that $R = \mergeop_{1 \leq i \leq l} R_i$ where $R_i$ is the result of evaluating the query $KNN(D_i, q, k)$. Consider the evaluation of the merge operator against two arbitrary result sets, $R = R_i \mergeop R_j$. It is clear that $|R| = |R_i| = @@ -1159,7 +1333,7 @@ that k-NN is $C(n)$-decomposable. Unfortunately, this classification brings with it a reduction in query performance as a result of the way result merges are performed. -As a concrete example of these costs, consider using the Bentley-Saxe +As a concrete example of these costs, consider using the logarithmic method to extend the VPTree~\cite{vptree}. The VPTree is a static, metric index capable of answering k-NN queries in $KNN(D, q, k) \in O(k \log n)$. One possible merge algorithm for k-NN would be to push all @@ -1176,7 +1350,7 @@ this would yield, \end{equation} The reason for this large increase in cost is the repeated application -of the merge operator. The Bentley-Saxe method requires applying the +of the merge operator. The logarithmic method requires applying the merge operator in a binary fashion to each partial result, multiplying its cost by a factor of $\log n$. Thus, the constant-time requirement of standard decomposability is necessary to keep the cost of the merge @@ -1222,22 +1396,22 @@ Even with this abuse, however, IRS cannot generally be considered decomposable; it is at best $C(n)$-decomposable. The reason for this is that matching the distribution requires drawing the appropriate number of samples from each partition of the data. Even in the special -case that $|D_0| = |D_1| = \ldots = |D_\ell|$, the number of samples +case that $|D_1| = |D_2| = \ldots = |D_\ell|$, the number of samples from each partition that must appear in the result set cannot be known in advance due to differences in the selectivity of the predicate across the partitions. \begin{example}[IRS Sampling Difficulties] - Consider three partitions of data, $D_0 = \{1, 2, 3, 4, 5\}, D_1 = - \{1, 1, 1, 1, 3\}, D_2 = \{4, 4, 4, 4, 4\}$ using bag semantics and + Consider three partitions of data, $D_1 = \{1, 2, 3, 4, 5\}, D_2 = + \{1, 1, 1, 1, 3\}, D_3 = \{4, 4, 4, 4, 4\}$ using bag semantics and an IRS query over the interval $[3, 4]$ with $k=12$. Because all three partitions have the same size, it seems sensible to evenly distribute the samples across them ($4$ samples from each partition). Applying the query predicate to the partitions results in the following, - $d_0 = \{3, 4\}, d_1 = \{3 \}, d_2 = \{4, 4, 4, 4\}$. + $d_1 = \{3, 4\}, d_2 = \{3 \}, d_3 = \{4, 4, 4, 4\}$. - In expectation, then, the first result set will contain $R_0 = \{3, + In expectation, then, the first result set will contain $R_1 = \{3, 3, 4, 4\}$ as it has a 50\% chance of sampling a $3$ and the same probability of a $4$. The second and third result sets can only be ${3, 3, 3, 3}$ and ${4, 4, 4, 4}$ respectively. Merging these @@ -1271,18 +1445,18 @@ query processing. \subsection{Configurability} -Amortized global reconstruction is built upon a fundamental trade-off -between insertion and query performance, that is governed by the number -of blocks a structure is decomposed into. The equal block method attempts -to address this by directly exposing $f(n)$, the number of blocks, as -a configuration parameter. However, this technique suffers from poor -insertion performance~\cite{overmars83} compared to the Bentley-Saxe -method, owing to the larger average reconstruction size required by -the fact that the blocks are of equal size. In fact, we'll show in +Decomposition-based dynamization is built upon a fundamental trade-off +between insertion and query performance, that is governed by the +number of blocks a structure is decomposed into. Both the equal +block and $k$-binomial method expose parameters to tune the number +of blocks in the structure, but these techniques suffer from poor +insertion performance in general. The equal block method in particular +suffers greatly from the larger block sizes~\cite{overmars83}, and the +$k$-binomial approach suffers the same problem. In fact, we'll show in Chapter~\ref{chap:tail-latency} that the equal block method is strictly -worse than Bentley-Saxe in experimental conditions for a given query +worse than the logarithmic method in experimental conditions for a given query latency in the trade-off space. There is a theoretical technique that -attempts to address this limitation by nesting the Bentley-Saxe method +attempts to address this limitation by nesting the logarithmic method inside of the equal block method, called the \emph{mixed method}, that has appeared in the theoretical literature~\cite{overmars83}. But this technique is clunky, and doesn't provide the user with a meaningful design @@ -1294,7 +1468,7 @@ the work. Many ``obvious'' options for tweaking the method, such as changing the rate at which levels grow, adding buffering, etc., result in constant-factor trade-offs, and thus are not relevant to the asymptotic bounds that these works are concerned with. It's worth noting that some -works based on \emph{applying} the Bentley-Saxe method introduce some +works based on \emph{applying} the logarithmic method introduce some form of configurability~\cite{pgm,almodaresi23}, usually inspired by the design space of LSM trees~\cite{oneil96}, but the full consequences of this parametrization in the context of dynamization have, to the @@ -1307,15 +1481,14 @@ in Chapter~\ref{chap:design-space}. One of the largest problems associated with classical dynamization techniques is the poor worst-case insertion performance. This results in massive insertion tail latencies. Unfortunately, solving -this problem within the Bentley-Saxe method itself is not a trivial +this problem within the logarithmic method itself is not a trivial undertaking. Maintaining the strict binary decomposition of the structure, -as Bentley-Saxe does, ensures that any given reconstruction cannot be -performed in advance, as it requires access to all the records in the -structure in the worst case. This limits the ability to use parallelism -to hide the latencies. +ensures that any given reconstruction cannot be performed in advance, +as it requires access to all the records in the structure in the worst +case. This limits the ability to use parallelism to hide the latencies. The worst-case optimized approach proposed by Overmars and von Leeuwen -abandons the binary decomposition of the Bentley-Saxe method, and is thus +abandons the binary decomposition of the logarithmic method, and is thus able to provide an approach for limiting this worst-case insertion bound, but it has a number of serious problems, @@ -1349,7 +1522,7 @@ In this chapter, we introduced the concept of a search problem, and showed how amortized global reconstruction can be used to dynamize data structures associated with search problems having certain properties. We examined several theoretical approaches for dynamization, including the -equal block method, the Bentley-Saxe method, and a worst-case insertion +equal block method, the logarithmic method, and a worst-case insertion optimized approach. Additionally, we considered several more classes of search problem, and saw how additional properties could be used to enable more efficient reconstruction, and support for efficiently deleting -- cgit v1.2.3