Ballot Types in Simulation
-
@rob said in Ballot Types in Simulation:
a lot of work has been done
Understood; I appreciate your intent in making sure I am aware of existing work that might apply.
At the moment, external notation is not an immediate concern for me as I am still in the more basic level of implementing semantics and behavior. As I conceive this thing, the ballots go from software to other software, not from humans to software.
-
@jack-waugh said in Ballot Types in Simulation:
At the moment, external notation is not an immediate concern for me
Ok, I mean, usually I like for things to be viewable by humans. But also, this does go beyond external notation because it parses them into a form that is usable by the program. It also makes the distinction you note between ballot types and tabulation methods.
Obviously its up to you to do it how you see best, but since you keep posting here your thoughts as you build things out, presumably so others can weigh in, this is me weighing in: I think having it able to import and export to a human readable, human editable format should typically be a first step on a project like this. If only to do regular sanity checks as you build things out.
Is there something else you are looking for?
-
@rob You are identifying candidates by name rather than index for the tallies. For determining the chances of our collaborating on code, how important is it that I imitate that practice?
I see that the structure you are using when equal ranking is allowed is that
ranks
is an array of arrays and the inner arrays list the candidates. I let your code parse "a=b>c=d" and it came up with{ranks: [["a", "b"], ["c", "d"]]}
. -
@rob Pressing "tabulate" does nothing in Firefox.
-
@rob
class PairwiseResults
defines.tabulate (ballots)
but that is never called. -
@jack-waugh Not sure "name" is the right word for what I identify candidates by, since you can just use a one character string, which in turn maps back to the full name. (in which case "key" might be a better word for it) But it also allows you use a full name. I aimed for flexibility.
I haven't looked at the code for a while, but you could probably use numbers as keys. The problem with that is it might confuse it unless you add a bit of logic to make it smarter.
Regardless I preferred by able to do both this:
a[5] c[4]
and this
Joe Smith[5] Jane Jones[4]
As for arrays when you have equal ranking, how else could you do it? You have to be able to have multiple members at each ranking. I'm not sure the best solution, but that is what I came up with. I don't think I did much if anything in terms of tabulating ranked ballots, mostly I did cardinal ballots.... I'm open to suggestions.
-
@rob said in Ballot Types in Simulation:
how else could you do it
I don't know that there is any other reasonable way to do it. I hadn't worked out a way, and I was just remarking that I understood how you were doing it as a result of my reverse engineering. I can see using the same format with names or IDs or indices.
I erred by not trying to draft in the first place a tally that would take equal ranking. Once such a tally is working, it won't care whether arbitrary and evil restrictions are imposed with respect to the ballots before they are handed to the tally. It is only up to the voting decision procedures to obey such restrictions or not, depending on what purpose they are designed for.
In regard to names, my idea has been that a given tallying algorithm would get called at first without names, since they have no bearing on the tally. The tally would return the set of candidates (by index) who tied for the win and a closure to be called later to report, rendered into DOM elements, the details of how the tally went. The candidate names would be supplied on this second call. But if you say it is your earnest opinion that the names should come along in the first call, I will change the design accordingly. I think there is something to be said for my putting some value on making it smooth for either of us to adapt code written for one context to run in the other. No need to duplicate effort in writing tallying algorithms, I suppose, if we can manage to make them understandable to each other.
-
@jack-waugh Sorry that Codepen doesn't tabulate, I must have been working on it and broken something. This one does, and is just a previous fork:
https://codepen.io/karmatics/pen/gOrLLxP
I did test it with numerical "names" for candidates so this works:
134: 0[5] 1[4] 2[2] 3[1] 4[0] 5[0]
64: 0[5] 1[4] 2[3] 3[1] 4[0] 5[0]
94: 0[3] 1[5] 2[4] 3[1] 4[0] 5[0]
70: 0[2] 1[2] 2[5] 3[2] 4[0] 5[0]
63: 0[0] 1[0] 2[0] 3[3] 4[4] 5[5]
55: 0[0] 1[0] 2[1] 3[3] 4[5] 5[4]
55: 0[0] 1[1] 2[4] 3[3] 4[5] 5[3]
48: 0[0] 1[0] 2[5] 3[3] 4[5] 5[5]
30: 0[1] 1[0] 2[1] 3[3] 4[3] 5[5]
30: 0[0] 1[1] 2[2] 3[5] 4[5] 5[4]
28: 0[2] 1[1] 2[0] 3[3] 4[3] 5[5]
27: 0[0] 1[0] 2[0] 3[3] 4[5] 5[5]
26: 0[0] 1[1] 2[3] 3[3] 4[5] 5[3]
22: 0[1] 1[0] 2[0] 3[3] 4[4] 5[5]
20: 0[1] 1[1] 2[0] 3[3] 4[3] 5[5]They are treated as strings by the tabulation logic, but you don't have to.
Also, notice this codepen, where it does rankings (but I don't know if it handles equal rankings, it probably will parse them but simply use the first member of each subarray, since I was using it on real election data from the infamous Burlington election.
https://codepen.io/karmatics/pen/PoRvYaX
Also notice how it uses single characters for the candidate "names" (to keep the data really small), but those are simply keys into a list (a.k.a. hash table) of full names. Keep in mind that hash lookup is ridiculously fast in Javascript, in case you were doing indexes into an array as an optimization. The latter is probably no faster.
a: Kiss b: Montroll c: Simpson d: Smith e: Wright f: w-i ------------ 840:e 355:a>b 326:a 271:e>d 256:e>b 234:a>b>d 200:b>a 178:b 147:e>b>d 145:b>a>d 139:b>d 125:a>d 124:d
-
-
BTW, you mentioned how equal ranks are done:
a=b>e>c=d
becomes:
{ ranks: [ ["a", "b"], ["e"], ["c", "d"] ] }
Another option might be:
{ ranks: [ "a=b", "e", "c=d" ] }
This simplifies the default case of no equal ranks, but allows a simple operation ( item.split('=') ) to get them into a list if needed.
-
@rob I prefer the current way, where it is completely parsed, to the alternative you mention, which would require further parsing (even so simple as with one
.split("=")
). -
I am posting to indicate that I have not abandoned the simulation project; I am gradually trying to progress it. I don't expect a response unless you think I have left something important out or am painting myself into a corner with the design choices I am laying out.
I asked myself: What are we going to read from the file directories and how will what we read figure in during prompting and execution?
At the indicative level, a voting system declares what form of ballot it requires.
Tactics, at the indicative level, will be able to answer given a ballot form, are they capable of generating ballots conforming thereto.
So, when the user selects a voting system, the app will offer the tactics that can produce ballots for that system.
Since tactics will have an indicative level and an executive level, they must comprise at least two files, so it makes sense to use a directory for each tactic.
So there will be one directory containing the subdirectories for the voting systems and one directory containing the subdirectories for the tactics. There is no need for the hierarchy of directories to reflect any kind of categorization of either. So, for example, there will not be a directory of ranking voting systems nor a directory of rating voting systems nor a directory of Condorcet-compliant voting systems, etc.
Example declarations of ballot types:
{ [0]: 'rating', finite: false, /* Continuous -- allows floating-point ratings. */ min: 0, max: 1, } { [0]: 'rating', finite: true, range: [0, 1, 2, 3, 4, 5], /* like STAR */ } { [0]: 'ranking', equal_ranking_allowed: true, }
Here's Approval:
{ [0]: 'rating', finite: true, range: [0, 1], /* Approval */ }