]> mj.ucw.cz Git - saga.git/commitdiff
Soft heaps: fixes.
authorMartin Mares <mj@ucw.cz>
Sat, 29 Mar 2008 14:21:25 +0000 (15:21 +0100)
committerMartin Mares <mj@ucw.cz>
Sat, 29 Mar 2008 14:21:25 +0000 (15:21 +0100)
opt.tex

diff --git a/opt.tex b/opt.tex
index 823f5ef06d058e80ab6233c9aa84787376fe3073..24b6d92b2568b26b9f091110d28b077604b6451a 100644 (file)
--- a/opt.tex
+++ b/opt.tex
@@ -17,19 +17,19 @@ Chazelle \cite{chazelle:softheap}. It is a~meldable priority queue, roughly
 similar to the Vuillemin's binomial heaps \cite{vuillemin:binheap} or Fredman's
 and Tarjan's Fibonacci heaps \cite{ft:fibonacci}. The soft heaps run faster at
 the expense of \df{corrupting} a~fraction of the inserted elements by raising
-their values (the values are however never decreased). This allows for
+their values (the values are however never lowered). This allows for
 an~trade-off between accuracy and speed controlled by a~parameter~$\varepsilon$.
 The heap operations take $\O(\log(1/\varepsilon))$ amortized time and at every
 moment at most~$\varepsilon n$ elements of the~$n$ elements inserted can be
 corrupted.
 
 \defnn{Soft heap operations}%
-The soft heap contains distinct elements from a~totally ordered universe and it
+The soft heap contains a~set of distinct items from a~totally ordered universe and it
 supports the following operations:
 \itemize\ibull
-\:$\<Create>(\varepsilon)$ --- create an~empty soft heap with the given accuracy parameter,
+\:$\<Create>(\varepsilon)$ --- create an~empty soft heap with the given accuracy parameter~$\varepsilon$,
 \:$\<Insert>(H,x)$ --- insert a~new element~$x$ to the heap~$H$,
-\:$\<Meld>(P,Q)$ --- merge two heaps into one, more precisely insert all elements of a~heap~$Q$
+\:$\<Meld>(P,Q)$ --- merge two heaps into one, more precisely move all elements of a~heap~$Q$
   to the heap~$P$, destroying~$Q$ in the process (both heaps must have the same~$\varepsilon$),
 \:$\<DeleteMin>(H)$ --- delete the minimum element of the heap~$H$ and return its value
   (optionally signalling that the value has been corrupted).
@@ -52,27 +52,28 @@ to select a~good pivot in Quicksort \cite{hoare:qsort}, leading to time complexi
 in the worst case.
 
 \defnn{Soft queues}
-The soft heap is built from \df{soft queues} (we will omit the adjective soft
+The soft heap is built from \df{soft queues} (we will usually omit the adjective soft
 in the rest of this section). Each queue has a~shape of a~binary tree.\foot{%
 Actually, Chazelle defines the queues as binomial trees, but he transforms them in ways that are
 somewhat counter-intuitive, albeit well-defined. We prefer describing the queues as binary
 trees with a~special distribution of values. In fact, the original C~code in the Chazelle's
-paper uses this representation internally.}
-Each vertex~$v$ of the tree remembers a~doubly-linked list $\<list>(v)$ of values. The
+paper \cite{chazelle:softheap} uses this representation internally.}
+Each vertex~$v$ of the tree remembers a~doubly-linked list of items. The
 item list in every left son will be used only temporarily and it will be kept
 empty between operations. Only right sons and the root have their lists
-permanently occupied. The former vertices will be called \df{white}, the latter
+permanently occupied. The left sons will be called \df{white}, the right ones
 \df{black.} (See the picture.)
 
-The first value in the list is called the \df{controlling key} of the vertex,
+The first value in every list is called the \df{controlling key} of the vertex,
 denoted by $\<ckey>(v)$. If the list is empty, we keep the most recently used
-value or we set $\<ckey>(v)=+\infty$. The \<ckey>'s obey the standard \df{heap order}
---- a~\<ckey> of a~parent is always less than the \<ckey>'s of its sons.
+value or we set $\<ckey>(v)=+\infty$. The \<ckey> obey the standard \df{heap order}
+--- a~\<ckey> of a~parent is always smaller than the \<ckey>'s of its sons.
 
 Each vertex is also assigned its \df{rank,} which is a~non-negative integer.
-The rank of leaves is always zero, the rank of every internal vertex must be strictly
-greater than the ranks of its sons. We define the rank of a~queue to be equal to the
-rank of its root vertex and similarly for its \<ckey>.
+The ranks of leaves are always zero, the rank of every internal vertex can be
+arbitrary, but it must be strictly greater than the ranks of its sons. We
+define the rank of the whole queue to be equal to the rank of its root vertex and
+similarly for its \<ckey>.
 
 A~queue is called \df{complete} if every two vertices joined by an~edge have rank
 difference exactly one. In other words, it is a~complete binary tree and the
@@ -82,8 +83,8 @@ ranks correspond to vertex heights.
 (black vertices contain items, numbers indicate ranks)}}
 
 \obs
-A~complete queue of rank~$k$ contains exactly~$2^{k+1}-1$ vertices, $2^k$~of which are
-black (by induction). Any other queue can be trivially embedded to a~complete queue of the same
+The complete queue of rank~$k$ contains exactly~$2^{k+1}-1$ vertices, $2^k$~of which are
+black (by induction). Any other queue can be trivially embedded to the complete queue of the same
 rank, which we will call the \df{master tree} of the queue. This embedding preserves vertex
 ranks, colors and the ancestor relation.
 
@@ -92,34 +93,35 @@ two queues of rank~$k-1$ under a~new root. The root will inherit the item list o
 of the original roots and also its \<ckey>. To preserve the heap order, we will choose
 the one whose \<ckey> is smaller.
 
-Sometimes, we will need to split a~queue to smaller queues. We will call this operation
+Sometimes, we will also need to split a~queue to smaller queues. We will call this operation
 \df{dismantling} the queue and it will happen only in cases when the item list in the root
 is empty. It suffices to remove the leftmost (all white) path going from the root. From
 a~queue of rank~$k$, we get queues of ranks $0,1,\ldots,k-1$, some of which may be missing
 if the original queue was not complete.
 
-We will now combine the soft queues to the soft heap.
-
 \figure{softheap2.eps}{\epsfxsize}{Joining and dismantling of soft queues}
 
+We will now define the real soft heap and the operations on it.
+
 \defn A~\df{soft heap} consists of:
 \itemize\ibull
 \:a~doubly linked list of soft queues of distinct ranks (in increasing order of ranks),
-  we will call the first queue the \df{head}, the last queue will be its \df{tail};
+  we will call the first queue the \df{head} of the list, the last queue will be its \df{tail};
 \:\df{suffix minima:} each queue contains a~pointer to the queue with minimum \<ckey>
 of those following it in the list;
-\:and a~global parameter~$r\in{\bb N}$, to be set depending on~$\varepsilon$.
+\:a~global parameter~$r$: an~even integer to be set depending on~$\varepsilon$.
 \endlist
 
 \>We will define the \df{rank} of a~heap as the highest of the ranks of its queues
 (that is, the rank of the heap's tail).
 
 The heap always keeps the \df{Rank invariant:} When a~root of any tree has rank~$k$,
-its leftmost path has length at least~$k/2$.
+its leftmost path contains at least~$k/2$ vertices.
+
+\paran{Operations on soft heaps}
 
-\para
 \em{Melding} of two soft heaps involves merging of their lists of queues. We disassemble
-the heap with the smaller maximum rank and we insert its queues to the other heap.
+the heap of the smaller rank and we insert its queues to the other heap.
 If two queues of the same rank~$k$ appear in both lists, we \em{join} them to
 a~single queue of rank~$k+1$ as already described and we propagate the new queue as
 a~\df{carry} to the next iteration, similarly to addition of binary numbers.
@@ -131,9 +133,9 @@ a~single-element heap and melding it to the destination heap.
 
 \algn{Creating a~new soft heap}
 \algo
-\algin A~parameter~$\varepsilon$.
+\algin The~parameter~$\varepsilon$ (the accuracy of the heap).
 \:Allocate memory for a~new heap structure~$H$.
-\:Initialize the list of queues in~$H$ as an~empty list.
+\:Initialize the list of queues in~$H$ to an~empty list.
 \:Set the parameter~$r$ to~$2\lceil\log(1/\varepsilon)\rceil+2$ (to be justified later).
 \algout A~newly minted soft heap~$H$.
 \endalgo
@@ -141,26 +143,26 @@ a~single-element heap and melding it to the destination heap.
 \algn{Melding of two soft heaps}
 \algo
 \algin Two soft heaps~$P$ and~$Q$.
-\:If the heap~$P$ has smaller rank than the heap~$Q$, exchange their item lists.
+\:If $\<rank>(P) < \<rank>(Q)$, exchange the item lists of~$P$ and~$Q$.
 \:$p\=\<head>(P)$.
-\brk\cmt{Whenever we run into an~end of a~list in this procedure, we assume that it contains
-an~empty queue of infinite rank.}
+\brk\cmt{Whenever we run into an~end of a~list in this procedure, we assume that
+there is an~empty queue of infinite rank there.}
 \:While $Q$ still has some queues:
 \::$q\=\<head>(Q)$.
 \::If $\<rank>(p) < \<rank>(q)$, then $p\=$ the successor of~$p$,
-\::else if $\<rank>(p) > \<rank>(q)$, remove~$q$ from~$Q$ and insert it before~$p$,
+\::else if $\<rank>(p) > \<rank>(q)$, remove~$q$ from~$Q$ and insert it to~$P$ before~$p$,
 \::otherwise (the ranks are equal, we need to propagate the carry):
-\:::$\<carry>=p$.
-\:::$p\=$ the successor of~$p$.
+\:::$\<carry>\=p$.
+\:::Remove~$p$ from~$P$ and set $p\=$ the original successor of~$p$.
 \:::While $\<rank>(q)=\<rank>(\<carry>)$:
 \::::Remove~$q$ from~$Q$.
 \::::$\<carry>\=\<join>(q, \<carry>)$.
 \::::$q\=\<head>(Q)$.
 \:::Insert~\<carry> before~$q$.
 \:Update the suffix minima: Walk with~$p$ backwards to the head of~$P$:
-\::$p'\=$ successor of~$p$.
+\::$p'\=\<suffix\_min>$ of the successor of~$p$.
 \::If $\<ckey>(p) < \<ckey>(p')$, set $\<suffix\_min>(p)\=p$.
-\::Otherwise set $\<suffix\_min>(p)\=\<suffix\_min>(p')$.
+\::Otherwise set $\<suffix\_min>(p)\=p'$.
 \:Destroy the heap~$Q$.
 \algout The merged heap~$P$.
 \endalgo
@@ -168,14 +170,14 @@ an~empty queue of infinite rank.}
 \algn{Insertion of an~element to a~soft heap}
 \algo
 \algin A~heap~$H$ and a~new element~$x$.
-\:Create a~new heap~$H'$ with the same parameters as~$H$. Let~$H'$ contain a~sole queue of rank~0,
+\:Create a~new heap~$H'$ of the same parameters as~$H$. Let~$H'$ contain a~sole queue of rank~0,
   whose only vertex has the element~$x$ in its item list.
 \:$\<Meld>(H,H')$.
 \algout An~updated heap~$H$.
 \endalgo
 
 \para
-So far, the mechanics of the soft heaps was almost identical to the binomial heaps
+So far, the mechanics of the soft heaps were almost identical to the binomial heaps
 and the reader could rightfully yawn. The things are going to get interesting
 now as we approach the parts where corruption of items takes place.
 
@@ -187,25 +189,25 @@ represented by a~common \<ckey>. This data-structural analogue of car pooling wi
 allow the items to travel at a~faster rate, but as only a~single item can be equal
 to the \<ckey>, all other items will be inevitably corrupted.
 
-We of course have to be careful about the size of the lists, as we must avoid corrupting
+We of course have to be careful about the size of the lists, because we must avoid corrupting
 too many items. We will control the growth according to the vertex ranks. Vertices
 with rank at most~$r$ will always contain just a~single item. Above this level,
-the higher is the rank, the longer list will we allow.
+the higher is the rank, the longer list will be allowed.
 
 \para
-\em{Deleting of minimum} will follow this principle. The minimum is easy to locate
+\em{Deletion of minimum} will be based on this principle. The minimum is easy to locate
 --- we follow the \<suffix\_min> of the head of the heap to the queue with the minimum
-\<ckey> and we look inside the item list of the root of this queue. We remove the \em{last}
-item from the list (we do not want the \<ckey> to change) and return it as the minimum.
-(It is not necessarily the real minimum of all items, but always the minimum of those
-uncorrupted.)
+\<ckey>. There we look inside the item list of the root of the queue. We remove the \em{last}
+item from the list (we do not want the \<ckey> to change) and we return it as the minimum.
+(It is not necessarily the real minimum of all items, but always the minimum of their
+possibly corrupted values.)
 
 If the list becomes empty, we \em{refill} it with items from the lower levels of the
-same tree. This can be best described recursively: We ask the left son to refill itself
-(remember that the left son is always white, so there are no items to lose). If the new
+same queue. This process can be best described recursively: We ask the left son to refill itself
+(remember that the left son is always white, so there are currently no items there). If the new
 \<ckey> of the left son is smaller than of the right son, we immediately move the left
 son's list to its parent. Otherwise, we exchange the sons and move the list from the
-new left son to the parent. This way, we obey the heap order and the same time we keep
+new left son to the parent. This way we obey the heap order and at the same time we keep
 the white left son free of items.
 
 Ocassionally, we repeat this process once again and we concatenate the resulting lists
@@ -216,10 +218,10 @@ or the difference in ranks between this vertex and its right son is at least two
 
 If refilling of the left son fails because there are no more items in that subtree
 (we report this by setting its \<ckey> to $+\infty$), the current vertex is no longer
-needed, as the items would just travel through it unmodified. We therefore want to
-remove it. Instead of deleting it directly, we will rather make it point to its former
-grandsons and we will remove the (now orhpaned) original son. This helps us to ensure
-that both sons always have the same rank, which will be useful for the analysis.
+needed --- the items would just pass through it unmodified. We therefore want to
+remove it. Instead of deleting it directly, we rather make it point to its former
+grandsons and we remove the (now orhpaned) original son. This helps us to ensure
+that both sons always keep the same rank, which will be useful for the analysis.
 
 When all refilling is done, we update the suffix minima by walking from the current
 queue to the head of the heap exactly as we did in the \<Meld> procedure.
@@ -234,11 +236,11 @@ completely, so no explicit counters are needed.
 
 Let us translate these ideas to real (pseudo)code:
 
-\algn{Deleting the minimum item of a~soft heap}
+\algn{Deleting the minimum item from a~soft heap}
 \algo
 \algin A~soft heap~$H$.
 \:Use \<suffix\_min> of the head queue of~$H$ to locate the queue~$q$ with the smallest \<ckey>.
-\:Remove the last element~$x$ of the item list in the root of~$q$.
+\:Remove the final element~$x$ of the item list in the root of~$q$.
 \:If the item list is empty:
 \::Count the vertices on the leftmost path of~$q$.
 \::If there are less than $\<rank>(q)$ of them:
@@ -248,7 +250,7 @@ Let us translate these ideas to real (pseudo)code:
 \:::Meld them back: $\<Meld>(H,H')$.
 \::Otherwise:
 \:::Call \<Refill> on the root of~$q$.
-\:::If $\<ckey>(q)=+\infty$ (no items left), remove the tree~$q$.
+\:::If $\<ckey>(q)=+\infty$ (no items left), remove the tree~$q$ from~$H$.
 \:::Recalculate the suffix minima.
 \algout The deleted minimum item~$x$ (possibly corrupted).
 \endalgo
@@ -258,7 +260,7 @@ Let us translate these ideas to real (pseudo)code:
 \algin A~soft queue and its vertex~$v$ with an~empty item list.
 \:Handle trivial cases: If~$v$ has no children or both have $\<ckey>=+\infty$,
   set $\<ckey>(v)$ to~$+\infty$ and return.
-\:Let \<left> and~\<right> denote the sons of~$v$.
+\:Let \<left> and~\<right> denote the respective sons of~$v$.
 \:Recurse: call $\<Refill>(\<left>)$.
 \:If $\<ckey>(\<left>) > \<ckey>(\<right>)$, swap the sons.
 \:Move the item list from \<left> to~$v$ (implying $\<ckey>(v)=\<ckey>(\<left>)$).
@@ -272,13 +274,14 @@ Let us translate these ideas to real (pseudo)code:
 \endalgo
 
 \paran{Analysis of accuracy}
-The description of the operations is complete, let us analyse their behavior
+The description of the operations is now complete, so let us analyse their behavior
 and verify that we have delivered what we promised --- first the accuracy of
 the structure, then the time complexity of operations. In the whole analysis,
-we will denote the total number of elements inserted in the history of the
-structure by~$n$. We will also assume that the threshold~$r$ is even.
+we will denote the total number of elements inserted during the history of the
+structure by~$n$. We will also frequently take advantage of knowing that the
+threshold~$r$ is even.
 
-We start by bounding the size of the item lists.
+We start by bounding the sizes of the item lists.
 
 \lemma
 For every vertex~$v$ of a~soft queue, the size $\ell(v)$ of its item list
@@ -288,7 +291,7 @@ $$\ell(v) \le \max(1, 2^{\lceil \<rank>(v)/2 \rceil - r/2}).$$
 \proof
 Initially, all item lists contain at most one item, so the ineqality trivially
 holds. Let us continue by induction. Melds can affect it only in the favorable
-direction (they sometimes move an~item list to a~vertex of a~higher rank)
+direction (they ocassionally move an~item list to a~vertex of a~higher rank)
 and so do deletes (they only remove items from lists). The only potentially
 dangerous place is the \<Refill> procedure.
 
@@ -299,7 +302,7 @@ $\<rank>(v)$ is odd or $\<rank>(w) < \<rank>(v)-1$ for any son~$w$ of~$v$ (remem
 that both sons have the same rank). In both cases, $\lceil\<rank>(w)/2\rceil \le
 \lceil\<rank>(v)/2\rceil - 1$. By the induction hypothesis, the size of each
 of the two joined lists is at most $2^{\max(1,\lceil\<rank>(v)/2\rceil - 1 - r/2)}$,
-so the result has at most $2^{\lceil\<rank>(v)/2\rceil - r/2}$ items. (The maximum
+so the new list has at most $2^{\lceil\<rank>(v)/2\rceil - r/2}$ items. (The maximum
 has disappeared since $\<rank>(v)>r$ and therefore the desired bound is at least~2.)
 \qed
 
@@ -311,7 +314,7 @@ At any given time, the heap contains at most~$n/2^{r-2}$ corrupted items.
 \proof
 We first prove an~auxiliary claim: The master trees of all queues contain at most~$n$
 black vertices. This follows by induction: If no deletions have taken place,
-there are exactly~$n$ of them, because insertion adds one black vertex and
+there are exactly~$n$ black vertices, because insertion adds one black vertex and
 melding preserves their number. A~deletion affects the master trees only when
 dismantling takes place and then it only removes a~black vertex.
 
@@ -330,59 +333,63 @@ the total number of corrupted items in this tree is at most:
 $$
 \sum_{i=r+1}^k 2^{k-i}\cdot 2^{\lceil i/2\rceil - r/2}
 = 2^{k-r/2} \cdot \sum_{i=r+1}^k 2^{\lceil i/2\rceil - i}
-\le 2^{k-r/2} \cdot \sum_{i=r+1}^k 2^{-i/2}
+\le 2^{k-r/2+1/2} \cdot \sum_{i=r+1}^k 2^{-i/2}
 \le 2^{k-r} \cdot \sum_{i=0}^\infty 2^{-i/2}.
 $$
 The sum of a~geometric series with quotient $2^{-1/2}$ is less than four, so the
-last formula is less than $2^{k-r+2}$. Since the tree contains $n_k=2^k$ black vertices,
-this makes less than $n_k/2^{k-2}$ corrupted items as we asserted.
+last expression is less than $2^{k-r+2}$. Since the tree contains $n_k=2^k$ black vertices,
+this makes less than $n_k/2^{r-2}$ corrupted items as we asserted.
 \qed
 
 \paran{Analysis of time complexity}
-Now we will analyse the amortized time complexity of the individual operations.
-We will show that if we charge $\O(r)$ time against every element inserted, it suffices
-to cover the cost of all other operations. We take a~look at the melds first.
+Now we will examine the amortized time complexity of the individual operations.
+We will show that if we charge $\O(r)$ time against every element inserted, it is enough
+to cover the cost of all other operations.
+
+\FIXME{Pointer machine and yardsticks}
+
+We take a~look at the melds first.
 
 \lemma\id{shmeld}%
 The amortized cost of a~meld is $\O(1)$, except for melds induced by dismantling
 which take $\O(\<rank>(q))$, where $q$~is the queue to be dismantled.
 
 \proof
-The real cost of a~meld of heaps $P$ and~$Q$ is the smaller of their ranks plus
-the time spent on carry propagation. The latter is easy to dispose of: since
-every time there is a~carry, the total number of trees in all heaps decreases
-by one, it suffices to charge $\O(1)$ against creation of a~tree. An~insert creates
-one tree, dismantling creates at most $\<rank>(q)$ trees, all other operations
-alter only the internal structure of trees.
+The real cost of a~meld of heaps $P$ and~$Q$ is linear in the smaller of
+their ranks, plus the time spent on carry propagation. The latter is easy to
+dispose of: Every time there is a~carry, the total number of trees in all
+heaps decreases by one. So it suffices to charge $\O(1)$ against creation of
+a~tree. An~insert creates one tree, dismantling creates at most $\<rank>(q)$
+trees, and all other operations alter only the internal structure of trees.
 
 As for the $\O(\min(\<rank>(P),\<rank>(Q)))$ part, let us assume for a~while that
 no dismantling ever takes place and consider the \df{meld forest.} It is a~forest
 whose leaves correspond to the $n$~single-element heaps constructed by \<Insert>
 and each internal vertex represents a~heap arisen from melding its sons. The left
-son will be the one with the greater (or equal) rank. We therefore want to bound
+son will be the one with the greater or equal rank. We therefore want to bound
 the sum of ranks of all right sons.
 
-For every right son, we will distribute the change for its rank~$k$ on all leaves
+For every right son, we will distribute the change for its rank~$k$ among all leaves
 in its subtree. There are at least $2^k$ such leaves. No leaf ever receives the same
 rank twice, because the ranks of right sons on every path from the root of the
-tree to a~leaf are strictly decreasing. (This holds because melding two heaps
-of the same rank always produces a~heap of higher rank.) Hence at most~$n/2^k$
+tree to a~leaf are strictly decreasing. (This holds because melding of two heaps
+always produces a~heap of a~strictly greater rank.) Hence at most~$n/2^k$
 right sons have rank~$k$ and the total time charged against the leaves is bounded by:
 $$
-\sum_{k=0}^{\rm max. rank}k\cdot {n\over 2^k} \le n\cdot\sum_{k=0}^\infty {k\over 2^k} = \O(n).
+\sum_{k=0}^{\rm max. rank}k\cdot {n\over 2^k} \le n\cdot\sum_{k=0}^\infty {k\over 2^k} = 2n.
 $$
 
 Let us return dismantling to the game. When a~queue is dismantled, melding the parts
 back to the heap takes $\O(\<rank>(q))$ time. We can therefore let the dismantling pay for it
-and omit such induced melds from the meld forest. As the rank of the heap is never increased
+and omit such induced melds from the meld forest. As the rank of a~heap is never increased
 by induced melds, the above calculation is still a~proper upper bound on the cost
 of the regular melds.
 \qed
 
-To estimate the time spent on deletions, we analyse the refills first.
+Before we estimate the time spent on deletions, we analyse the refills.
 
 \lemma
-Every call of the \<Refill> procedure spends time $\O(1)$ amortized.
+Every invokation of the \<Refill> procedure takes time $\O(1)$ amortized.
 
 \proof
 When \<Refill> is called from the \<DeleteMin> operation, it recurses on a~subtree of the
@@ -391,7 +398,7 @@ and the upper part where list concatenation and thus also corruption takes place
 we visit the lower part during the recursion, we spend at worst $\O(r)$ time there.
 We will prove that the total time spent in the upper parts during the whole life of the
 data structure is $\O(n)$. Since each upper vertex can perform at most two calls to the lower
-part, the total time spent in the lower parts is $\O(rn)$. All this can be pre-paid by the
+part, the total time spent in the lower parts is $\O(rn)$. All this can be prepaid by the
 inserts.
 
 Let us focus on the upper part. There are three possibilities of what can happen
@@ -401,7 +408,7 @@ when we visit a~vertex:
 
 \:We delete it: Every vertex deleted has to have been created at some time in the past.
 New vertices are created only during inserts and melds (when joining two trees) and
-we have already shown that these operations have constant amortized complexity. So the
+we have already shown that these operations have constant amortized complexity. Then the
 same must hold for deletions.
 
 \:We recurse twice and concatenate the lists: The lists are disassembled only when
@@ -411,11 +418,11 @@ leaves and every internal vertex has outdegree two, so the total number of conca
 is at most~$n$. Each of them can be performed in constant time as the list is doubly linked.
 
 \:We recurse only once: This occurs only if the rank is even and the gap between the
-rank of this vertex and its sons is small. It therefore cannot happen twice in a~row,
-so it is clearly dominated by the other possibilities.
+rank of this vertex and its sons is equal to~1. It therefore cannot happen twice in a~row,
+thus it is clearly dominated by the cost of the other possibilities.
 
 \endlist
-\>The total cost of all operations on the upper part is therefore $\O(n)$.
+\>The total cost of all steps in the upper part is therefore $\O(n)$.
 \qed
 
 It remains to examine the rest of the \<DeleteMin> operation.
@@ -427,12 +434,17 @@ Every \<DeleteMin> takes $\O(1)$ time amortized.
 Aside from refilling, which is $\O(1)$ by the previous lemma, the \<DeleteMin>
 takes care of the Rank invariant. This happens by checking the length of the leftmost
 path and dismantling the tree if the length is too far from the tree's rank~$k$.
-The leftmost path is however always visited by the call to \<Refill>, so we can
-account the check on the refilling. The same holds for disassembling. We then have
-to pay $\O(k)$ for melding the trees back to the heap, but since there are at most
-$k/2$ trees, a~subtree of rank at least $k/2$ must have been deleted. This tree
-contained at least $2^{k/2}$ vertices which are now permanently gone from the
-data structure, so we can charge the cost of the meld against these vertices.
+When the invariant is satisfied, the leftmost path is visited by the subsequent
+call to \<Refill>, so we can account the check on the refilling.
+
+When we are dismantling, we have to pay $\O(k)$ for the operation itself and
+another $\O(k)$ for melding the trees back to the heap. Since we have produced at most
+$k/2$ subtrees of distinct ranks, some subtree of rank $k/2$ or more must be missing.
+Its master tree contained at least $2^{k/2}$ vertices which are now permanently gone
+from the data structure, so we can charge the cost against them.
+A~single vertex can participate in the master trees of several dismantlings, but their
+ranks are always strictly increasing. By the same argument as in the proof of
+Lemma \ref{shmeld} (complexity of \<Meld>), each vertex pays $\O(1)$.
 
 We must not forget that \<DeleteMin> also has to recalculate the suffix minima.
 In the worst case, it requires touching $k$~trees. Because of the Rank invariant,
@@ -446,8 +458,8 @@ Now we can put the bits together and laurel our effort with the following theore
 \thmn{Performance of soft heaps, Chazelle \cite{chazelle:softheap}}
 A~soft heap with error rate~$\varepsilon$ ($0<\varepsilon\le 1/2$) processes
 a~sequence of operations starting with an~empty heap and containing $n$~\<Insert>s
-in time $\O(n\log(1/\varepsilon))$. At every moment, the heap contains at most
-$\varepsilon n$ corrupted items.
+in time $\O(n\log(1/\varepsilon))$ on the Pointer machine. At every moment, the
+heap contains at most $\varepsilon n$ corrupted items.
 
 \proof
 We set the parameter~$r$ to~$2+2\lceil\log (1/\varepsilon)\rceil$. The rest follows