About vote bubbles¶
This document talks about vote bubbles.
This page contains code snippets (lines starting with >>>), which are
being tested during our development workflow. The following
snippet initializes the demo project used throughout this page.
>>> from lino_seggi.projects.seggi1.startup import *
>>> obj = seats.Board.objects.get(id=1)
>>> obj
Board #1 ('Riigikogu')
>>> rt.show(seats.VotesByBoard, obj, column_names = "id user user__id delegate delegate__id *")
==== =================================== ==== ======================= ====
ID User ID Delegate ID
---- ----------------------------------- ---- ----------------------- ----
1 Hans Altenberg 5 Andreas Arens 3
3 Andreas Arens 3 Ulrike Charlier 9
4 Annette Arens 4 Berta Ernst 15
5 Alfons Ausdemwald 6 Hildegard Hilgers 23
6 Laurent Bastiaensen 7 Josef Jonas 29
7 Marc Chantraine 10 Laura Laschet 33
9 Ulrike Charlier 9 Annette Arens 4
10 Charlotte Collard 8 Laurent Bastiaensen 7
11 Dorothée Demeulenaere 12 Charlotte Collard 8
12 Daniel Dericum 11 Bernd Evertz 16
13 Dorothée Dobbelstein 14 Josef Jonas 29
14 Dorothée Dobbelstein-Demeulenaere 13 Marc Malmendier 36
15 Daniel Emonts 18 Annette Arens 4
16 Edgar Engels 19 Marc Chantraine 10
17 Berta Ernst 15 Charlotte Collard 8
19 Eberhart Evers 17 Edgar Engels 19
20 Bernd Evertz 16 Luc Faymonville 20
21 Luc Faymonville 20 Irene Ingels 25
23 Germaine Gernegroß 21 Marc Malmendier 36
24 Gregory Groteclaes 22 Laurent Bastiaensen 7
25 Henri Hilgers 24 Edgar Engels 19
26 Hildegard Hilgers 23 Henri Hilgers 24
27 Irene Ingels 25 Karl Kaivers 31
29 Jacqueline Jacobs 27 Melissa Meessen 37
30 Jérémy Jansen 26 Rando Roosi 2
31 Johann Johnen 28 Laurent Bastiaensen 7
32 Josef Jonas 29 Charlotte Collard 8
33 Jan Jousten 30 Daniel Dericum 11
35 Karl Kaivers 31 Henri Hilgers 24
36 Guido Lambertz 32 Laura Laschet 33
37 Laura Laschet 33 Hans Altenberg 5
38 Line Lazarus 34 Dorothée Demeulenaere 12
39 Josefine Leffin 35 Eberhart Evers 17
41 Marc Malmendier 36 Hildegard Hilgers 23
42 Melissa Meessen 37 Josef Jonas 29
43 Marie-Louise Meier 39 Laura Laschet 33
44 Michael Mießen 38 Josefine Leffin 35
==== =================================== ==== ======================= ====
>>> collected, bubbles = obj.detect_bubbles()
>>> for chain in collected:
... print(chain)
(2 has 1 direct votes:
··(26 has 0 direct votes:
>>> for chain in bubbles:
... print(chain)
(29 has 3 direct votes:
··(7 has 3 direct votes:
····(8 has 2 direct votes:
······(12 has 1 direct votes:
········(34 has 0 direct votes:
······(15 has 1 direct votes:
········(4 has 2 direct votes:
··········(9 has 1 direct votes:
············(3 has 1 direct votes:
··············(5 has 1 direct votes:
················(33 has 3 direct votes:
··················(10 has 1 direct votes:
····················(19 has 2 direct votes:
······················(17 has 1 direct votes:
························(35 has 1 direct votes:
··························(38 has 0 direct votes:
······················(24 has 2 direct votes:
························(23 has 2 direct votes:
··························(6 has 0 direct votes:
··························(36 has 2 direct votes:
····························(13 has 0 direct votes:
····························(21 has 0 direct votes:
························(31 has 1 direct votes:
··························(25 has 1 direct votes:
····························(20 has 1 direct votes:
······························(16 has 1 direct votes:
································(11 has 1 direct votes:
··································(30 has 0 direct votes:
··················(32 has 0 direct votes:
··················(39 has 0 direct votes:
··········(18 has 0 direct votes:
····(22 has 0 direct votes:
····(28 has 0 direct votes:
··(14 has 0 direct votes:
··(37 has 1 direct votes:
····(27 has 0 direct votes:
(2 has 1 direct votes:
··(26 has 0 direct votes:
id |
user |
delegate |
1 |
A |
E |
2 |
B |
C |
3 |
C |
D |
4 |
D |
E |
5 |
E |
F |
After 1st loop we have:
Chain(E, [A, D]) Chain(C, [B]) Chain(D, [C]) Chain(F, [E])
After reducing the chains:
Chain(F, [Chain(E, [Chain(A), Chain(D, [Chain(C, [B])])])])
id |
user |
delegate |
1 |
A |
E |
2 |
B |
C |
3 |
C |
D |
4 |
D |
E |
5 |
E |
A |
After 1st loop we have:
Chain(E, [A, Chain(D, [Chain(C, [B])])]) Chain(A, [E])
After reducing the chains:
Chain(E, [Chain(A), [E]), Chain(D, [Chain(C, [B])])])
Old stuff:
How to detect and resolve vote bubbles.
Let’s say we have the following series of votes:
id |
seqno |
user |
delegate |
xyz |
|
1 |
1 |
A |
E |
||
2 |
2 |
A |
B |
||
3 |
1 |
B |
C |
||
4 |
1 |
C |
D |
||
5 |
1 |
D |
A |
||
6 |
1 |
E |
A |
||
7 |
2 |
E |
F |
In our example there are four possibilities:
A1-E1 : A gets their first choice, E gets their first choice
A1-E2 : A gets their first choice, E gets their 2nd choice
A2-E1 : A gets their 2nd choice, E gets their first choice
A2-E2 : A gets their 2nd choice, E gets their 2nd choice
The system needs an algorithm that detects the case that causes least bubbling to the whole system.
The algorithm must decide which of the alternative votes to “use” and which ones to “disable”.
Let’s look at the results in each of these four cases. For each permutation, we can build a list of “vote chains”. A vote chain is an ordered sequence of users who voted for each other, without duplicates.
In case A1-E1 we have 3 vote chains:
A -> E
B -> C -> D -> A
E -> A
We can say:
In case A1-E2 we have one single vote chain:
B -> C -> D -> A -> E -> F
We can say:
User F is the favorite, everybody wants him.
In case A2-E1 we get two vote chains:
E -> A -> B -> C -> D
D -> A
In case A2-E2 we get three vote chains:
A -> B -> C -> D
D -> A
E -> F
More observations:
If there are 2 votes with 2 choices, we have 4 possible permutations.
If E would add a third vote, this would add two more permutations (A1-E3 and A2-E3), so we would have 6 possible permutations.
In general, the number of permutations for n users giving r votes each is:
For example if we had 5 users and each of them gave 3 votes, we would have 5! / 2! = 5*4*3 = 60 possible permutations:
Next step: how to evaluate the different possibilities?
Edge case:
If A votes for B and B for A, both without any second choice, then the system should tell them that their vote is void, which means that they must either vote for somebody else or add a second choice.

