The -bit binary counter is a boolean array A[0...k-1] that stores a number in binary, with A[0] as the least significant bit.
- Initially all bits are
0(i.e. the counter is0). - Each index
brepresents the bit for
The structure supports one operation: increment(), which adds .
b = 0
while b < k and A[b] == 1:
A[b] = 0 # unset bit
b = b + 1
if b < k:
A[b] = 1 # set bitThis operation flips some number of consecutive 1s to 0, and then sets the first found 0 to 1. This sequence mimics addition by carrying the 1 to the next iteration (bit).
Example Of A 5-Bit Binary Counter
If , then the binary counter represents only bits.
- To represent the number (binary
01101), the boolean array stores[1, 0, 1, 1, 0]- Note how is the least significant (rightmost) digit.
If we run
increment()on this, then:
- We traverse through the array, flipping consecutive ‘s to ‘s;
b = 0 -> A[0] = 1 -> [0, 0, 1, 1, 0 ] -> b ++- We stop if we either reach the end, or we encounter our first
0:
b = 1 -> A[1] = 0 -> ...- If we encounter our first
0instead of reaching the end, flip it to1:
... -> 1 < 5 -> [0, 1, 1, 1, 0]The result is the binary
01110of
Worst-Case Analysis Of increment()
The run length is the number of iterations of the while loop in increment(), i.e., the number of consecutive 1s before the first 0.
The true cost of increment() is thus proportional to the run length.
- The worst-case run length is , so the worst-case time per operation is .
- Over increments, this gives a pessimistic bound of .
While some increments flip many bits (are costly), amortised analysis shows that the average cost per increment is low.
The run length is not necessarily equal to the true cost, as it doesn't account for setting the first found
0to1
Total Cost Example
- When the counter is :
- No iterations (
run_length = 0)- No units of effort
total_cost = 0- When the counter is :
- One trailing
1is flipped, i.e. the increment operation iterates once (run_length = 1)- There is unit of effort
total_cost = ) + 1 = 1- When the counter is :
- One trailing
1is flipped (run_length = 1), and the first encountered0is flipped.- There are unit of effort
total_cost = 1 + 2 = 3- When the counter is :
- One trailing
1is flipped (run_length = 1)- There is unit of effort
total_cost = 3 + 1 = 4- When the counter is :
- Two trailing
1are flipped (run_length = 2), and the first encountered0is flipped.- There is unit of effort
total_cost = 4 + 3 = 7- And so on…
Aggregate Method On K-Bit Binary Counter
To apply this method, we analyse how often each bit flips over n increments. The key idea is to group operations by their run length, i.e., the number of consecutive 1s before the first 0.
run_length = 0- These are the cases where
A[0] = 0, requiring just settingA[0] = 1( unit of effort) - This happens for even values, which are half the numbers.
- Therefore, there are counter values with
A[0] = 0(approximate as it depends on where the counter stops)
- These are the cases where
run_length = 1- Considering the remaining values (odd numbers), all of them have a
1in their LSD. - But of those values, half are of the form of the form
...11, and the other half is...01 run_length = 1are counter values withA[0] = 1andA[1] = 0requiring flippingA[0]to0in the iterations, and settingA[1]to1at the end (2 units of effort)- Therefore, there are counter values
- Considering the remaining values (odd numbers), all of them have a
Extending this logic (up to ), results in:
| Run Length | … | ||||||
|---|---|---|---|---|---|---|---|
| Values | … |
To compute the total cost, multiply each group count by its respective effort.
| Run Length | … | ||||||
|---|---|---|---|---|---|---|---|
| Values | … | ||||||
| Units Of Effort | unit | units | units | units | units | units | … |
| Respective Effort | … |
For example, values with run_length 1 require units of effort each, so total effort for those values is
Therefore, the sum of all efforts is
This infinite sum converges to :
However, the counts are approximate (rounded down), the actual sequence of increments may end before reaching very large run lengths, and the summation ignores any partial increments or leftover bits.
Therefore, this sum provides an upper bound on the total cost:
Hence, the total time over increments is , and the amortized cost per increment is:
Accounting Method On K-Bit Binary Counter
To apply this method to the increment operation, we break it down into two atomic tasks:
- The task of flipping a bit from
1to0- This step occurs inside the
whileloop and may repeat multiple times per operation. - This only happens to bits that were previously set (
= 1). - Each iteration (i.e. each flip) takes time.
- This step occurs inside the
- The task of setting a bit from
0to1- This happens once per
increment, after exiting the loop. - It also takes time.
- It runs at most once, as if all bits are already
1(i.e. the counter is at ), the loop clears all bits and no1is set.
- This happens once per
The key is to assign enough coins per increment so that each operation can:
- Pay for its own flipping and setting costs.
- Save extra coins as credit when setting bits to
1, which can later be used to pay for flipping those bits back to0in future operations.
Assume that coin pays for effort during any part of the increment operation.
Then coin can be allocated each time a bit is set to 1 (just before A[b] = 1 executes).
The coins are then used as follows:
- coin is then used for the actual bit-setting
- The remaining coins are stored as credit on that bit for future use.
Later, when the bit is flipped from 1 to 0 (in the loop) during a future increment, this credit is then used to pay:
- Each iteration of the loop flips a bit to
0, costing coin per iteration - Since each set bit has coins stored on it, we can afford to flip it up to coins
Thus, as long as there’s coins, there’s always enough credit to cover all future un-sets. This ensures:
- No operation goes into debt
- The total amortised cost is bounded by coins per increment, which is .
Potential Method On K-Bit Binary Counter
We define a potential function as the number of bits set to 1 in the counter after the -th increment operation.
- represents the “stored work”, each
1will eventually need to be flipped back to0, costing one unit each. - Initially, the counter is all zeroes, so .
- In general, for all , and the maximum potential is when all bits are set.
Let’s analyse the amortised cost of one increment() operation:
- When an
increment()is performed, several bits may flip from1to0, and exactly one bit flips from0to1. - Suppose the number of
1 -> 0transitions is (i.e., the number of iterations of the while loop). - Then, the total number of bit operations is .
The change in potential is thus:
- If , then
- If , then
From the amortised cost:
Substituting the two expressions into it results in:
In both cases, , so the amortised cost per operation is . Over increments, the total amortised time is .
