Assign4: Banzhaf Power Index


"It's not the voting that's democracy; it's the counting." – Tom Stoppard, Jumpers

Block voting systems

It's said that "every vote counts", but does every vote count equally? A block voting system such as the US Electoral College makes for an interesting case study in analyzing the relative voting power of each block in a system where blocks have different weights.

In a block voting system, each block has an assigned number of votes, and the votes for one block are cast in unison. In the US electoral system, California has a block of 55 votes to New Mexico's 5. You might ask: does this mean that California wields 10 times the influence of New Mexico in affecting the election outcome? Let's explore further!

One measure of a block's importance or voting "power" is the count of election outcomes in which that the block's vote is critical. A critical or swing vote is one that changes the election outcome. The count of critical votes is used in computing the Banzhaf Power Index, a measure of voting power in a block voting system.

Banzhaf Power Index

For a given voting block B, we count the situations in which B is a critical voter by identifying those winning coalitions in which B can participate but the coalition would not win if B does not join; that is, B supplied the critical vote that was able to swing the election.

Consider this example system of three voting blocks:

Block Block Count
Lions 50
Tigers 49
Bears 1

First let's enumerate the possible ways a voting coalition could shape up: Lions+Tigers+Bears, Lions+Tigers, Lions+Bears, Tigers+Bears, Lions, Tigers, Bears.

Assume winning an election requires a strict majority. This system has 100 total votes, so a winning coalition must amass 51 or more votes to have a majority.

Of these seven possible coalitions above, three are winning coalitions: L+T+B, L+T, and L+B.

Now, for each winning coalition, consider which of its blocks are a critical voter:

A block is a critical voter if its support for the coalition changes the outcome. A winning coalition would no longer be winning if a critical voter left the coalition. Note that Lions is a critical voter for the coalition L+T+B, but neither Tigers nor Bears are.

Counting the critical votes for each block gives us the following data:

Block Critical Votes
Lions 3
Tigers 1
Bears 1

The Banzhaf Power Index expresses a block's voting power as the percentage of situations in which this block is a critical voter. This system has 5 total critical votes of which Lions have 3, so Lions control 3/5 or 60% of the critical votes.

To convert from the count of critical votes to the Power Index, total all critical votes in the system, and compute the percentage of each block's critical votes. The table below shows the power indexes for the sample system:

Block Banzhaf Power Index
Lions 60% (= 3/5)
Tigers 20% (= 1/5)
Bears 20% (= 1/5)

The power indexes for all blocks sum to 100%. Comparing relative percentages shows the difference in voting power among the blocks.

Tigers and Bears have equivalent voting power, despite the Tigers' much larger block count. The small uptick in block count for the Lions gives it three times the voting power the Tigers. Apparently the lion's share of the votes really does go the Lions! (sorry… I could not resist)

Your task

You are to write the function

Vector<int> computePowerIndexes(Vector<int>& blocks)

that receives a Vector of size N containing the block counts for a block voting system. The function counts critical votes to determine the voting power per block. The result returned from the function is a Vector of size N with Banzhaf power index for each block. For example, calling computePowerIndexes on the vector of block counts { 50, 49, 1} returns a vector of per-block power indexes { 60, 20, 20 }.

Although the explanation above describes the process in terms of first finding coalitions and then determining which participants are critical, the actual code is easier to structure by instead proceeding to count the critical votes specific to a target block and repeating that process for all blocks.

After testing and debugging your function, predict what you expect to be the Big O of the computePowerIndex function. Then use the timing operation to measure the execution time over 4 or more different sizes. (There is information on how to use SimpleTest for timing in the merge task writeup). Choose sizes so that the largest operation completes in under a minute or so. Answer these questions in short_answer.txt:

Notes

References

Extensions