Skip to content

Instantly share code, notes, and snippets.

@dsernst
Last active November 22, 2017 22:28
Show Gist options
  • Save dsernst/624a29e252951bbd5f773ca47edfa89c to your computer and use it in GitHub Desktop.
Save dsernst/624a29e252951bbd5f773ca47edfa89c to your computer and use it in GitHub Desktop.

Goal: An algorithm to calculate an elected legislator's "Representation Score".

Legislative agenda

We have a set of legislative bills, uniquely identified with keys like "2016-11-01-160553" or "2017-03-07-170089", that are the agenda items of a jurisdiction's legislature.

The set grows by 40 bills per week on average. As of 2017-03-12, it has 602 elements.

Each bill has a 1-week window in which it can be voted upon by the citizens in the jurisdiction via the Liquid platform.

Voter registration

Before they can vote, a citizen must have registered with the platform to prove their legal voter eligibility. This is to ensure one-person-one-vote and that all voters are legal residents of the jurisdiction.

Voting

On any bill, each citizen can vote yea, nay, or not vote.

Delegation

A citizen may have previously designated a personal delegate, who is another citizen of the jurisdiction. If a citizen does not vote on a particular bill, their delegate's position will be inherited as their own, like a proxy.

That delegate may themselves have selected a delegate, and this proxy voting power passes transitively. Thus, if Alice has delegated to Bob, and Bob has delegated to Charles, and on a particular bill Alice and Bob do not vote directly but Charles does, Charles' decision will count as 3 votes (recorded with depths of 0, 1, and 2, respectively).

This creates a delegation chain: a linked list from one citizen to their delegate. It terminates when a citizen has no delegate, or has delegated to someone already in the linked list (which would otherwise create an endless cycle).

If a citizen does not vote on a bill, nor does anyone in their delegation chain, no vote is recorded.

Tallying votes

After the 1-week window passes, the votes on a bill are tallied and summarized as such:

{
  bill_uid: '2017-03-07-170089',
  votes_yea: 25544,
  votes_nay: 29512,
}

The jurisdiction's elected legislator is presented this information about their constituents' positions.

The elected legislator then casts their vote on the bill in the legally-recognized legislative body. The platform records this position:

{
  bill_uid: '2017-03-07-170089',
  votes_yea: 25544,
  votes_nay: 29512,
  elected_rep_vote: 'yea',
}

Desired output:

A single number — e.g. 0, 65, 100 — that conveys a summary "score" of how well an elected legislator is representing their constituents. This number may be displayed as a letter grade — e.g. A, B+, F — which may be calculated the standard A > 90, 60 > F way, or may be graded on a curve among the elected legislators.

@dsernst
Copy link
Author

dsernst commented Apr 7, 2017

Latest solution:

  • votes_with_constituents: increment for every individual constituent vote aligned the same way as elected rep's vote.
  • votes_against_constituents: increment for every individual constituent vote aligned the opposite way as elected rep's vote.

image


Simulating the examples from the previous comment:

Rep Mary

{
  bill_uid: '2017-03-07-170089',
  votes_yea: 35544,
  votes_nay: 342,
  elected_rep_vote: 'yea',
}
{
  bill_uid: '2017-03-07-170041',
  votes_yea: 65,
  votes_nay: 62,
  elected_rep_vote: 'nay',
}

Which implies:

votes_with_constituents = 35544 + 62 = 35606
votes_against_constituents = 342 + 65 = 407

score = 35606 / (35606 + 407) = 0.9886985 = 98.87%

Rep Nathan

{
  bill_uid: '2017-03-07-170089',
  votes_yea: 35544,
  votes_nay: 342,
  elected_rep_vote: 'nay',
}
{
  bill_uid: '2017-03-07-170041',
  votes_yea: 65,
  votes_nay: 62,
  elected_rep_vote: 'yea',
}

Which implies:

votes_with_constituents = 342 + 65 = 407
votes_against_constituents = 35544 + 62 = 35606

score = 407 / (407 + 35606) = 0.0113015 = 1.13%


That looks much better, and still seems acceptably simple to understand & explain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment