Compare commits
10 Commits
0ee5fd3285
...
a60283b9de
Author | SHA1 | Date |
---|---|---|
Adrian Gunnar Lauterer | a60283b9de | |
RunasSudo | 582fdb8fe2 | |
RunasSudo | 4cf9053681 | |
RunasSudo | c140ef0a90 | |
RunasSudo | 9fc0457844 | |
RunasSudo | 74d8829fbd | |
RunasSudo | ed44f4f8a2 | |
RunasSudo | f488d50f4d | |
RunasSudo | ba6ad8964f | |
RunasSudo | eaf864062d |
File diff suppressed because it is too large
Load Diff
|
@ -325,6 +325,8 @@
|
|||
|
||||
\subsection\label{surplus-wig-sf}\paragraph If \textit{--papers} is \textit{both}, divide the elected candidate's surplus by their progress total.
|
||||
|
||||
% FIXME: Update this for new --transferable-only, --surplus-assume-total flags
|
||||
|
||||
\subsectionc\paragraph If \textit{--papers} is \textit{transferable}, for each parcel held by the elected candidate, multiply the number of transferable ballots in the parcel by the parcel's value, and sum the products. Divide the elected candidate's surplus by the sum.
|
||||
|
||||
\subsectionc\paragraph If \textit{--papers} is \textit{subtract_nontransferable}, for each parcel held by the elected candidate, multiply the number of non-transferable ballots in the parcel by the parcel's value, and sum the products. Subtract the sum from the elected candidate's progress total. Divide the elected candidate's surplus by the difference.
|
||||
|
|
|
@ -13,11 +13,12 @@ The preset dropdown allows you to choose from a hardcoded list of preloaded STV
|
|||
| Meek STV | Advanced STV rules designed for computer counting, recognised by the Proportional Representation Society of Australia (Victoria–Tasmania) as the superior STV system. | | |
|
||||
| • OpenTally Meek | Recommended rules for Meek STV. Operates according to the original 1987 Hill–Wichmann–Woodall ‘Algorithm 123’ specification ([*The Computer Journal* 1987;30(3):277–81](https://www.dia.govt.nz/diawebsite.NSF/Files/meekm/%24file/meekm.pdf)), except that (a) ties are broken backwards then at random, (b) fixed-point arithmetic with 5 decimal places is used, and (c) candidates are elected on strictly exceeding the quota. | | ✓ |
|
||||
| • Meek STV (2006) | Operates according to Hill's 2006 revisions ([*Voting Matters* 2006;(22):7–10](http://www.votingmatters.org.uk/ISSUE22/I22P2.pdf)). This is the algorithm referred to in OpenSTV/OpaVote as ‘Meek STV’, and forms the basis of New Zealand's Meek STV rules. | [E1] | ✓ |
|
||||
| • Meek STV (New Zealand) | Operates according to Schedule 1A of the [*Local Electoral Regulations 2001*](https://www.legislation.govt.nz/regulation/public/2001/0145/latest/DLM57125.html). | [E1] | ✓ |
|
||||
| Australian Senate STV | Rules from the [*Commonwealth Electoral Act 1918*](https://www.legislation.gov.au/Details/C2020C00400/Html/Text#_Toc59107700), using the unweighted inclusive Gregory method. | [E2] [E3] [E4] | ✓ |
|
||||
| NSW Local Government STV | Rules from the [*Local Government (General) Regulation 2021*](https://legislation.nsw.gov.au/view/html/inforce/current/sl-2021-0460), using the weighted inclusive Gregory method. | [E2] [E5] | ✓ |
|
||||
| Western Australia STV | Rules from the [*Electoral Act 1907* (WA)](https://www.legislation.wa.gov.au/legislation/prod/filestore.nsf/FileURL/mrdoc_29498.pdf/$FILE/Electoral%20Act%201907%20-%20[17-a0-06].pdf), using the weighted inclusive Gregory method. | [E2] [E3] | |
|
||||
| Australian Capital Territory STV | Rules from the [*Electoral Act 1992* (ACT)](https://www.legislation.act.gov.au/View/a/1992-71/current/PDF/1992-71.PDF), using the exclusive Gregory method. | | ✓ |
|
||||
| • Meek STV (New Zealand) | Rules from Schedule 1A of the [*Local Electoral Regulations 2001*](https://www.legislation.govt.nz/regulation/public/2001/0145/latest/DLM57125.html). | [E1] | ✓ |
|
||||
| Australian Senate STV | Rules from section 273 of the [*Commonwealth Electoral Act 1918*](https://www.legislation.gov.au/Details/C2020C00400/Html/Text#_Toc59107700), using the unweighted inclusive Gregory method. | [E2] [E3] [E4] | ✓ |
|
||||
| NSW Local Government STV | Rules from Schedule 5 of the [*Local Government (General) Regulation 2021*](https://legislation.nsw.gov.au/view/html/inforce/2022-12-16/sl-2021-0460#sch.5), using the weighted inclusive Gregory method. | [E2] [E5] | ✓ |
|
||||
| Victorian Legislative Council STV | Rules from section 114A of the [*Electoral Act 2002* (Vic)](https://content.legislation.vic.gov.au/sites/default/files/2022-06/02-23aa064%20authorised.pdf), using the unweighted inclusive Gregory method. | [E2] | ✓ |
|
||||
| Western Australia STV | Rules from Schedule 1 of the [*Electoral Act 1907* (WA)](https://www.legislation.wa.gov.au/legislation/prod/filestore.nsf/FileURL/mrdoc_29498.pdf/$FILE/Electoral%20Act%201907%20-%20[17-a0-06].pdf), using the weighted inclusive Gregory method. | [E2] [E3] [E5] | |
|
||||
| Australian Capital Territory STV | Rules from Schedule 4 of the [*Electoral Act 1992* (ACT)](https://www.legislation.act.gov.au/View/a/1992-71/current/PDF/1992-71.PDF), using the exclusive Gregory method. | | ✓ |
|
||||
| Minneapolis STV | Rules from chapter 167 of the [*Minneapolis Code of Ordinances*](https://library.municode.com/mn/minneapolis/codes/code_of_ordinances?nodeId=COOR_TIT8.5EL_CH167MUELRUCO), using the weighted inclusive Gregory method. | [E6] | ✓ |
|
||||
| Cambridge STV | Rules in force in Cambridge, Massachusetts, using random sample transfers. These rules are derived from the [former chapter 54A of the Massachusetts General Laws](https://www.cambridgema.gov/-/media/Files/electioncommission/massachusettsgenerallawschapter54a.pdf), but have by regulation been modified to incorporate the procedures set out in Article IX of the former [1938 Charter of the City of Cincinnati](https://catalog.hathitrust.org/Record/001754258). See also [here](https://web.archive.org/web/20081118104049/http://www.fairvote.org/media/1993countmanual.pdf). | | ✓ |
|
||||
| Dáil Éireann STV | Rules from the [*Electoral Act 1992* (Ireland)](http://www.irishstatutebook.ie/eli/1992/act/23/enacted/en/print), using stratified random sample transfers. | [E4] [E7] | ✓ |
|
||||
|
@ -34,11 +35,11 @@ Exceptions:
|
|||
* [E2] When breaking ties backwards, OpenTally applies a recursive method rather than the method described in the legislation. The OpenTally developers regard the method described in the legislation as a defect. For an independent discussion, see <a href="https://dl.acm.org/doi/10.1145/3014812.3014837">Conway et al.</a>
|
||||
* [E3] A tie between 2 candidates for the final vacancy will be broken backwards then at random, rather than the method described in the legislation.
|
||||
* [E4] Bulk exclusion is not performed, as the prescribed rules are more conservative than OpenTally's. See also the section on *Bulk exclusion* for further discussion.
|
||||
* [E5] The legislation is drafted such that a consistent interpretation is impossible – see <a href="https://github.com/AndrewConway/ConcreteSTV/blob/main/nsw/NSWLocalCouncilLegislation2021Commentary.md">Conway</a> for a discussion. In practice, the New South Wales Electoral Commission has applied the ‘by parcel’ method of rounding subtransfers, which OpenTally follows.
|
||||
* [E5] The legislation is drafted such that a consistent interpretation is impossible – see <a href="https://github.com/AndrewConway/ConcreteSTV/blob/main/nsw/NSWLocalCouncilLegislation2021Commentary.md">[1]</a>, <a href="https://yingtongli.me/blog/2022/07/15/wigm-legislation.html">[2]</a> for a discussion. In practice, the New South Wales and Western Australia Electoral Commissions have applied the ‘by parcel’ method of segmented exclusion and rounding subtransfers, which OpenTally follows.
|
||||
* [E6] The ‘mathematically eliminated by the sum of all ranked-choice votes comparison’ is not implemented, and undeclared write-in candidates are not distinguished.
|
||||
* [E7] The ‘quarter of a quota’ provision is disregarded when determining whether to defer surplus distributions.
|
||||
* [E8] The distribution of a surplus is not deferred if it exactly equals the difference between the 2 trailing continuing candidates.
|
||||
* [E9] The distribution of a surplus is not deferred if a bulk exclusion could be performed and it could not change the bulk exclusion, even if it could change which candidate is last.
|
||||
* [E9] The distribution of a surplus is deferred if a bulk exclusion could be performed and it could not change the bulk exclusion, even if it could change which candidate is last.
|
||||
* [E10] No distinction is made between stages and substages (during exclusion). This affects only the numbering of stages and not the result.
|
||||
* [E11] By default, the quota is always calculated to 2 decimal places. For full ERS76 (ERS73) compliance, set *Round quota to 0 d.p.* when the quota is more than 100 (100 or more).
|
||||
|
||||
|
@ -108,11 +109,12 @@ Random sample methods are also supported, but also not recommended:
|
|||
|
||||
A random sample method will usually be used with a *Quota criterion* set to *>=*.
|
||||
|
||||
### Ballots to examine in surplus transfer (--transferable-only/--subtract-nontransferable)
|
||||
### Ballots to examine in surplus transfer (--transferable-only/--surplus-assume-total)
|
||||
|
||||
* *Include non-transferable ballots* (default): When this option is selected, all ballots of the transferring candidate are examined. Non-transferable ballots are always exhausted at the relevant surplus fractions. This is the method typically used with the weighted inclusive Gregory or Meek methods.
|
||||
* *Use transferable ballots only* (--transferable-only): When this option is selected, only transferable ballots of the transferring candidate are examined. Non-transferable ballots are exhausted only if the value of the transferable ballots is less than the surplus. This is the method typically used with other surplus distribution methods.
|
||||
* *Subtract non-transferables* (--transferable-only --subtract-nontransferable): Same as *Use transferable ballots only*, but the value of the transferable ballots is calculated by subtracting the value of non-transferable ballots from the progress total. This has effect only as far as concerns rounding.
|
||||
* *Include non-transferable ballots* (default): When this option is selected, all ballots of the transferring candidate are examined. The denominator of the surplus fraction is the total value of the ballots. Non-transferable ballots are always exhausted at the relevant surplus fractions. This is the method typically used with the weighted inclusive Gregory or Meek methods.
|
||||
* *Assume progress total* (--surplus-assume-total): Same as *Include non-transferable ballots*, but the denominator of the surplus fraction is the candidate's recorded progress total. This has effect only as far as concerns rounding, and only in the weighted inclusive Gregory method.
|
||||
* *Use transferable ballots only* (--transferable-only): When this option is selected, only transferable ballots of the transferring candidate are examined. The denominator of the surplus fraction is the total value of the transferable ballots. Non-transferable ballots are exhausted only if the value of the transferable ballots is less than the surplus. This is the method typically used with other surplus distribution methods.
|
||||
* *Subtract non-transferables* (--transferable-only --surplus-assume-total): Same as *Use transferable ballots only*, but the value of the transferable ballots is calculated by subtracting the value of non-transferable ballots from the progress total. This has effect only as far as concerns rounding, and only in the weighted inclusive Gregory method.
|
||||
|
||||
### (Gregory) Exclusion method (--exclusion)
|
||||
|
||||
|
@ -120,6 +122,7 @@ When *Surplus method* is set to a Gregory method, this option controls how candi
|
|||
|
||||
* *Single stage* (default): When excluding candidate(s), transfer all their ballots in one stage.
|
||||
* *By value*: When excluding candidate(s), transfer their ballots in descending order of accumulated transfer value. Each transfer of all ballots of a certain transfer value forms a separate stage, i.e. if a transfer allows another candidate to meet the quota, no further ballots are transferred to that candidate.
|
||||
* *FPV then by value*: When excluding candidate(s), transfer their first preference ballot papers in the first stage, then transfer ballot papers received on transfers as in *By value*.
|
||||
* *By source*: When excluding candidate(s), transfer their ballots according to the candidate from which those ballots were received, in the order the transferring candidates were elected or excluded. Each transfer of all ballots received from a certain candidate forms a separate stage.
|
||||
* *By parcel (by order)*: When excluding a candidate, transfer their ballot ballots one parcel at a time, in the order each was received. Each parcel forms a separate stage. This option cannot be combined with bulk exclusion.
|
||||
* *Reset and re-iterate*: When excluding candidate(s), reset the count from the distribution of first preferences, disregarding the excluded candidates.
|
||||
|
|
|
@ -12,6 +12,7 @@ STV-counting software is frequently validated empirically by comparing the resul
|
|||
| Australian Senate STV | [2019 NSW Senate election](https://results.aec.gov.au/24310/Website/SenateDownloadsMenu-24310-Csv.htm) | EasyCount (official) | |
|
||||
| Australian Capital Territory STV | [2020 Kurrajong Legislative Assembly election](https://www.elections.act.gov.au/elections_and_voting/2020_legislative_assembly_election/ballot-paper-preference-data-2020-election) | [eVACS 2020](https://www.elections.act.gov.au/elections_and_voting/electronic_voting_and_counting) (official) | ✓ |
|
||||
| NSW Local Government STV | [2021 City of Albury Council election](https://pastvtr.elections.nsw.gov.au/LG2101/albury/councillor) | PRCC Vote Count (official) | ✓ |
|
||||
| Victorian Legislative Council STV | [2022 Northern Metropolitan Region Legislative Council election](https://www.vec.vic.gov.au/results/state-election-results/2022-state-election-results/results-by-region/northern-metropolitan-region-results) | Results sheet (official) | ✓ |
|
||||
| Minneapolis STV | [2009 Minneapolis Board of Estimate & Taxation election](https://vote.minneapolismn.gov/results-data/election-results/2009/bet/) | Results sheet (official) | ✓ |
|
||||
| Minneapolis STV | [2013 Minneapolis Parks & Recreation Commissioner At Large election](https://vote.minneapolismn.gov/results-data/election-results/2013/park-board-at-large/) | Results sheet (official) | ✓ |
|
||||
| Minneapolis STV | [2021 Minneapolis Board of Estimate & Taxation election](https://vote.minneapolismn.gov/results-data/election-results/2021/bet/) | Results sheet (official) | ✓ |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!--
|
||||
* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2022 Lee Yingtong Li (RunasSudo)
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -44,6 +44,7 @@
|
|||
<option value="senate">Australian Senate STV</option>
|
||||
<option value="act">Australian Capital Territory STV</option>
|
||||
<option value="nswlg">NSW Local Government STV</option>
|
||||
<option value="viclc">Victorian Legislative Council STV</option>
|
||||
<option value="wa">Western Australia STV</option>
|
||||
<option value="meeknz">Meek STV (New Zealand)</option>
|
||||
<option value="minneapolis">Minneapolis STV</option>
|
||||
|
@ -122,6 +123,7 @@
|
|||
<label>
|
||||
<select id="selPapers">
|
||||
<option value="both" selected>Include non-transferable ballots</option>
|
||||
<option value="assume_progress_total">Assume progress total</option>
|
||||
<option value="transferable">Use transferable ballots only</option>
|
||||
<option value="subtract_nontransferable">Subtract non-transferables</option>
|
||||
</select>
|
||||
|
@ -134,6 +136,7 @@
|
|||
<select id="selExclusion">
|
||||
<option value="single_stage" selected>Single stage</option>
|
||||
<option value="by_value">By value</option>
|
||||
<option value="first_prefs_then_by_value">FPV then by value</option>
|
||||
<option value="by_source">By source</option>
|
||||
<option value="parcels_by_order">By parcel (by order)</option>
|
||||
<option value="reset_and_reiterate">Reset and re-iterate</option>
|
||||
|
|
|
@ -164,6 +164,29 @@ function changePreset() {
|
|||
document.getElementById('selPapers').value = 'both';
|
||||
document.getElementById('selExclusion').value = 'by_value';
|
||||
document.getElementById('selTies').value = 'backwards,random';
|
||||
} else if (document.getElementById('selPreset').value === 'viclc') {
|
||||
document.getElementById('selQuotaCriterion').value = 'geq';
|
||||
document.getElementById('selQuota').value = 'droop';
|
||||
document.getElementById('selQuotaMode').value = 'static';
|
||||
document.getElementById('chkBulkElection').checked = true;
|
||||
document.getElementById('chkBulkExclusion').checked = false;
|
||||
document.getElementById('chkDeferSurpluses').checked = false;
|
||||
document.getElementById('chkImmediateElect').checked = true;
|
||||
document.getElementById('txtMinThreshold').value = '0';
|
||||
document.getElementById('selNumbers').value = 'rational';
|
||||
document.getElementById('txtPPDP').value = '0';
|
||||
document.getElementById('chkRoundQuota').checked = true;
|
||||
document.getElementById('txtRoundQuota').value = '0';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '0';
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_order';
|
||||
document.getElementById('selMethod').value = 'uig';
|
||||
document.getElementById('selPapers').value = 'both';
|
||||
document.getElementById('selExclusion').value = 'first_prefs_then_by_value';
|
||||
document.getElementById('selTies').value = 'backwards,random';
|
||||
} else if (document.getElementById('selPreset').value === 'wa') {
|
||||
document.getElementById('selQuotaCriterion').value = 'geq';
|
||||
document.getElementById('selQuota').value = 'droop';
|
||||
|
@ -181,11 +204,11 @@ function changePreset() {
|
|||
document.getElementById('txtRoundVotes').value = '0';
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'per_ballot';
|
||||
document.getElementById('selSumTransfers').value = 'by_parcel';
|
||||
document.getElementById('selSurplus').value = 'by_order';
|
||||
document.getElementById('selMethod').value = 'wig';
|
||||
document.getElementById('selPapers').value = 'both';
|
||||
document.getElementById('selExclusion').value = 'by_source';
|
||||
document.getElementById('selPapers').value = 'assume_progress_total';
|
||||
document.getElementById('selExclusion').value = 'parcels_by_order';
|
||||
document.getElementById('selTies').value = 'backwards,random';
|
||||
} else if (document.getElementById('selPreset').value === 'act') {
|
||||
document.getElementById('selQuotaCriterion').value = 'geq';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2022 Lee Yingtong Li (RunasSudo)
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -121,12 +121,12 @@ pub struct SubcmdOptions {
|
|||
#[clap(help_heading=Some("STV VARIANTS"), long)]
|
||||
transferable_only: bool,
|
||||
|
||||
/// (Gregory STV) If --transferable-only, calculate value of transferable papers by subtracting value of non-transferable papers
|
||||
/// (Gregory STV) When calculating surplus fractions, assume the progress total is the total value of all the candidate's papers
|
||||
#[clap(help_heading=Some("STV VARIANTS"), long)]
|
||||
subtract_nontransferable: bool,
|
||||
surplus_assume_total: bool,
|
||||
|
||||
/// (Gregory STV) Method of exclusions [default: single_stage] [possible values: single_stage, by_value, by_source, parcels_by_order, reset_and_reiterate]
|
||||
#[clap(help_heading=Some("STV VARIANTS"), long, possible_values=&["single_stage", "by_value", "by_source", "parcels_by_order", "wright", "reset_and_reiterate"], default_value="single_stage", value_name="method", hide_possible_values=true, hide_default_value=true)]
|
||||
#[clap(help_heading=Some("STV VARIANTS"), long, possible_values=&["single_stage", "by_value", "first_prefs_then_by_value", "by_source", "parcels_by_order", "wright", "reset_and_reiterate"], default_value="single_stage", value_name="method", hide_possible_values=true, hide_default_value=true)]
|
||||
exclusion: String,
|
||||
|
||||
/// (Meek STV) NZ Meek STV behaviour: Iterate keep values one round before candidate exclusion
|
||||
|
@ -302,7 +302,7 @@ where
|
|||
cmd_opts.surplus.into(),
|
||||
cmd_opts.surplus_order.into(),
|
||||
cmd_opts.transferable_only,
|
||||
cmd_opts.subtract_nontransferable,
|
||||
cmd_opts.surplus_assume_total,
|
||||
cmd_opts.exclusion.into(),
|
||||
cmd_opts.meek_nz_exclusion,
|
||||
cmd_opts.sample.into(),
|
||||
|
|
|
@ -233,7 +233,7 @@ where
|
|||
|
||||
// Count votes
|
||||
|
||||
let mut parcels_next_prefs= Vec::new();
|
||||
let mut parcels_next_prefs = Vec::new();
|
||||
|
||||
let mut transferable_ballots = N::new();
|
||||
let mut transferable_votes = N::new();
|
||||
|
@ -241,7 +241,7 @@ where
|
|||
let mut exhausted_ballots = N::new();
|
||||
let mut exhausted_votes = N::new();
|
||||
|
||||
for parcel in parcels {
|
||||
for (parcel_num, parcel) in parcels.into_iter().enumerate() {
|
||||
// Count next preferences
|
||||
let result = super::next_preferences(state, parcel.votes);
|
||||
|
||||
|
@ -253,20 +253,32 @@ where
|
|||
exhausted_ballots += &result.exhausted.num_ballots;
|
||||
exhausted_votes += &result.exhausted.num_ballots * &parcel.value_fraction;
|
||||
|
||||
parcels_next_prefs.push((parcel.value_fraction, parcel.source_order, result));
|
||||
// Determine which column of the transfer table to use
|
||||
let table_column_num = match opts.round_subtransfers {
|
||||
RoundSubtransfersMode::ByValueAndSource => Some(parcel.source_order),
|
||||
RoundSubtransfersMode::ByParcel => Some(parcel_num),
|
||||
_ => Some(0)
|
||||
};
|
||||
|
||||
parcels_next_prefs.push((parcel.value_fraction, table_column_num, result));
|
||||
}
|
||||
|
||||
// Calculate and print surplus fraction
|
||||
|
||||
let total_ballots = &transferable_ballots + &exhausted_ballots;
|
||||
let total_votes = &transferable_votes + &exhausted_votes;
|
||||
let mut total_votes = &transferable_votes + &exhausted_votes;
|
||||
|
||||
let count_card = state.candidates.get_mut(elected_candidate).unwrap();
|
||||
count_card.ballot_transfers = -&total_ballots;
|
||||
|
||||
if opts.transferable_only && opts.subtract_nontransferable {
|
||||
// Override transferable_votes
|
||||
transferable_votes = count_card.votes.clone() - exhausted_votes;
|
||||
if opts.surplus_assume_total {
|
||||
// Override total_votes
|
||||
total_votes = count_card.votes.clone();
|
||||
|
||||
if opts.transferable_only {
|
||||
// Override transferable_votes
|
||||
transferable_votes = count_card.votes.clone() - exhausted_votes;
|
||||
}
|
||||
}
|
||||
|
||||
let mut surplus_denom = calculate_surplus_denom(&surplus, &transferable_ballots, &transferable_votes, &total_ballots, &total_votes, opts);
|
||||
|
@ -320,16 +332,12 @@ where
|
|||
surplus.clone(), surplus_fraction.clone(), surplus_numer.clone(), surplus_denom.clone()
|
||||
);
|
||||
|
||||
for (value_fraction, source_order, result) in parcels_next_prefs {
|
||||
for (value_fraction, table_column_num, result) in parcels_next_prefs {
|
||||
for (candidate, entry) in result.candidates.into_iter() {
|
||||
// Record transfers
|
||||
transfer_table.add_transfers(
|
||||
&value_fraction,
|
||||
match opts.round_subtransfers {
|
||||
RoundSubtransfersMode::ByValueAndSource => Some(source_order),
|
||||
RoundSubtransfersMode::ByParcel => None, // Force new column per parcel
|
||||
_ => Some(0)
|
||||
},
|
||||
table_column_num,
|
||||
candidate,
|
||||
&entry.num_ballots
|
||||
);
|
||||
|
@ -366,11 +374,7 @@ where
|
|||
// Record exhausted votes
|
||||
transfer_table.add_exhausted(
|
||||
&value_fraction,
|
||||
match opts.round_subtransfers {
|
||||
RoundSubtransfersMode::ByValueAndSource => Some(source_order),
|
||||
RoundSubtransfersMode::ByParcel => None, // Force new column per parcel
|
||||
_ => Some(0)
|
||||
},
|
||||
table_column_num,
|
||||
&result.exhausted.num_ballots
|
||||
);
|
||||
|
||||
|
@ -447,7 +451,7 @@ where
|
|||
}
|
||||
votes_remain = false;
|
||||
}
|
||||
ExclusionMethod::ByValue => {
|
||||
ExclusionMethod::ByValue | ExclusionMethod::FirstPreferencesThenByValue => {
|
||||
// Exclude by value
|
||||
let excluded_with_votes: Vec<&&Candidate> = excluded_candidates.iter()
|
||||
.filter(|c| { let cc = &state.candidates[*c]; !cc.finalised && !cc.parcels.is_empty() })
|
||||
|
@ -456,55 +460,97 @@ where
|
|||
if excluded_with_votes.is_empty() {
|
||||
votes_remain = false;
|
||||
} else {
|
||||
// If candidates to exclude still having votes, select only those with the greatest value
|
||||
let max_value = excluded_with_votes.iter()
|
||||
.map(|c| state.candidates[*c].parcels.iter()
|
||||
.map(|p| &p.value_fraction)
|
||||
.max().unwrap())
|
||||
.max().unwrap()
|
||||
.clone();
|
||||
|
||||
votes_remain = false;
|
||||
|
||||
let mut votes = Vec::new();
|
||||
|
||||
for excluded_candidate in excluded_with_votes.iter() {
|
||||
let count_card = state.candidates.get_mut(*excluded_candidate).unwrap();
|
||||
let mut cc_parcels = Vec::new();
|
||||
cc_parcels.append(&mut count_card.parcels);
|
||||
if opts.exclusion == ExclusionMethod::FirstPreferencesThenByValue
|
||||
&& excluded_with_votes.iter().any(|c| state.candidates[*c].parcels.iter().any(|p| p.source_order == 0))
|
||||
{
|
||||
// If candidates to exclude still having votes, select only those with first preferences
|
||||
for excluded_candidate in excluded_with_votes.iter() {
|
||||
let count_card = state.candidates.get_mut(*excluded_candidate).unwrap();
|
||||
let mut cc_parcels = Vec::new();
|
||||
cc_parcels.append(&mut count_card.parcels);
|
||||
|
||||
// Filter out just those votes with max_value
|
||||
let mut remaining_parcels = Vec::new();
|
||||
// Filter out just those first preferences
|
||||
let mut remaining_parcels = Vec::new();
|
||||
|
||||
for mut parcel in cc_parcels {
|
||||
if parcel.value_fraction == max_value {
|
||||
count_card.ballot_transfers -= parcel.num_ballots();
|
||||
for mut parcel in cc_parcels {
|
||||
if parcel.source_order == 0 {
|
||||
count_card.ballot_transfers -= parcel.num_ballots();
|
||||
|
||||
let votes_transferred = parcel.num_votes();
|
||||
votes.append(&mut parcel.votes);
|
||||
let votes_transferred = parcel.num_votes();
|
||||
votes.append(&mut parcel.votes);
|
||||
|
||||
// Update votes
|
||||
checksum -= &votes_transferred;
|
||||
count_card.transfer(&-votes_transferred);
|
||||
} else {
|
||||
remaining_parcels.push(parcel);
|
||||
// Update votes
|
||||
checksum -= &votes_transferred;
|
||||
count_card.transfer(&-votes_transferred);
|
||||
} else {
|
||||
remaining_parcels.push(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
if !remaining_parcels.is_empty() {
|
||||
votes_remain = true;
|
||||
}
|
||||
|
||||
// Leave remaining votes with candidate
|
||||
count_card.parcels = remaining_parcels;
|
||||
}
|
||||
|
||||
if !remaining_parcels.is_empty() {
|
||||
votes_remain = true;
|
||||
// Group all votes of one value in single parcel
|
||||
parcels.push(Parcel {
|
||||
votes,
|
||||
value_fraction: N::one(), // By definition, first preferences have value of 1
|
||||
source_order: 0, // Set this later
|
||||
});
|
||||
} else {
|
||||
// If candidates to exclude still having votes, select only those with the greatest value
|
||||
let max_value = excluded_with_votes.iter()
|
||||
.map(|c| state.candidates[*c].parcels.iter()
|
||||
.map(|p| &p.value_fraction)
|
||||
.max().unwrap())
|
||||
.max().unwrap()
|
||||
.clone();
|
||||
|
||||
for excluded_candidate in excluded_with_votes.iter() {
|
||||
let count_card = state.candidates.get_mut(*excluded_candidate).unwrap();
|
||||
let mut cc_parcels = Vec::new();
|
||||
cc_parcels.append(&mut count_card.parcels);
|
||||
|
||||
// Filter out just those votes with max_value
|
||||
let mut remaining_parcels = Vec::new();
|
||||
|
||||
for mut parcel in cc_parcels {
|
||||
if parcel.value_fraction == max_value {
|
||||
count_card.ballot_transfers -= parcel.num_ballots();
|
||||
|
||||
let votes_transferred = parcel.num_votes();
|
||||
votes.append(&mut parcel.votes);
|
||||
|
||||
// Update votes
|
||||
checksum -= &votes_transferred;
|
||||
count_card.transfer(&-votes_transferred);
|
||||
} else {
|
||||
remaining_parcels.push(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
if !remaining_parcels.is_empty() {
|
||||
votes_remain = true;
|
||||
}
|
||||
|
||||
// Leave remaining votes with candidate
|
||||
count_card.parcels = remaining_parcels;
|
||||
}
|
||||
|
||||
// Leave remaining votes with candidate
|
||||
count_card.parcels = remaining_parcels;
|
||||
// Group all votes of one value in single parcel
|
||||
parcels.push(Parcel {
|
||||
votes,
|
||||
value_fraction: max_value,
|
||||
source_order: 0, // Set this later
|
||||
});
|
||||
}
|
||||
|
||||
// Group all votes of one value in single parcel
|
||||
parcels.push(Parcel {
|
||||
votes,
|
||||
value_fraction: max_value,
|
||||
source_order: 0, // source_order is unused in this mode
|
||||
});
|
||||
}
|
||||
}
|
||||
ExclusionMethod::BySource => {
|
||||
|
|
|
@ -1081,8 +1081,8 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
ExclusionMethod::ByValue | ExclusionMethod::BySource | ExclusionMethod::ParcelsByOrder => {
|
||||
// Exclusion in parts compatible only with Gregory method
|
||||
ExclusionMethod::ByValue | ExclusionMethod::FirstPreferencesThenByValue | ExclusionMethod::BySource | ExclusionMethod::ParcelsByOrder => {
|
||||
// Segmented exclusion compatible only with Gregory method
|
||||
gregory::exclude_candidates(state, opts, excluded_candidates, complete_type);
|
||||
}
|
||||
ExclusionMethod::ResetAndReiterate => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2022 Lee Yingtong Li (RunasSudo)
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -81,9 +81,9 @@ pub struct STVOptions {
|
|||
#[builder(default="false")]
|
||||
pub transferable_only: bool,
|
||||
|
||||
/// (Gregory STV) If --transferable-only, calculate value of transferable papers by subtracting value of non-transferable papers
|
||||
/// (Gregory STV) When calculating surplus fractions, assume the progress total is the total value of all the candidate's papers
|
||||
#[builder(default="false")]
|
||||
pub subtract_nontransferable: bool,
|
||||
pub surplus_assume_total: bool,
|
||||
|
||||
/// (Gregory STV) Method of exclusions
|
||||
#[builder(default="ExclusionMethod::SingleStage")]
|
||||
|
@ -169,7 +169,7 @@ impl STVOptions {
|
|||
if self.surplus != SurplusMethod::Meek {
|
||||
if self.surplus_order != SurplusOrder::BySize { flags.push(self.surplus_order.describe()); }
|
||||
if self.transferable_only { flags.push("--transferable-only".to_string()); }
|
||||
if self.subtract_nontransferable { flags.push("--subtract-nontransferable".to_string()); }
|
||||
if self.surplus_assume_total { flags.push("--surplus-assume-total".to_string()); }
|
||||
if self.exclusion != ExclusionMethod::SingleStage { flags.push(self.exclusion.describe()); }
|
||||
}
|
||||
if self.surplus == SurplusMethod::Meek && self.meek_nz_exclusion { flags.push("--meek-nz-exclusion".to_string()); }
|
||||
|
@ -238,14 +238,10 @@ impl STVOptions {
|
|||
return Err(STVError::InvalidOptions("--constraint-mode repeat_count requires a Gregory method for --surplus"));
|
||||
}
|
||||
}
|
||||
if self.subtract_nontransferable {
|
||||
if self.surplus_assume_total {
|
||||
if self.surplus != SurplusMethod::WIG {
|
||||
// Invalid because other methods do not distinguish between ballots of different value during surplus transfer
|
||||
return Err(STVError::InvalidOptions("--subtract-nontransferable requires --surplus wig"));
|
||||
}
|
||||
if !self.transferable_only {
|
||||
// Invalid because nontransferables are only subtracted with --transferable-only
|
||||
return Err(STVError::InvalidOptions("--subtract-nontransferable requires --transferable-only"));
|
||||
return Err(STVError::InvalidOptions("--surplus-assume-total requires --surplus wig"));
|
||||
}
|
||||
}
|
||||
if !self.immediate_elect {
|
||||
|
@ -526,6 +522,8 @@ pub enum ExclusionMethod {
|
|||
SingleStage,
|
||||
/// Transfer the ballot papers of an excluded candidate in descending order of accumulated transfer value
|
||||
ByValue,
|
||||
/// Transfer the first preferences for an excluded candidate, then ballot papers received on transfers in descending order of accumulated transfer value
|
||||
FirstPreferencesThenByValue,
|
||||
/// Transfer the ballot papers of an excluded candidate according to the candidate who transferred the papers to the excluded candidate, in the order the transferring candidates were elected or excluded
|
||||
BySource,
|
||||
/// Transfer the ballot papers of an excluded candidate parcel by parcel in the order received
|
||||
|
@ -540,6 +538,7 @@ impl ExclusionMethod {
|
|||
match self {
|
||||
ExclusionMethod::SingleStage => "--exclusion single_stage",
|
||||
ExclusionMethod::ByValue => "--exclusion by_value",
|
||||
ExclusionMethod::FirstPreferencesThenByValue => "--exclusion first_prefs_then_by_value",
|
||||
ExclusionMethod::BySource => "--exclusion by_source",
|
||||
ExclusionMethod::ParcelsByOrder => "--exclusion parcels_by_order",
|
||||
ExclusionMethod::ResetAndReiterate => "--exclusion reset_and_reiterate",
|
||||
|
@ -552,6 +551,7 @@ impl<S: AsRef<str>> From<S> for ExclusionMethod {
|
|||
match s.as_ref() {
|
||||
"single_stage" => ExclusionMethod::SingleStage,
|
||||
"by_value" => ExclusionMethod::ByValue,
|
||||
"first_prefs_then_by_value" => ExclusionMethod::FirstPreferencesThenByValue,
|
||||
"by_source" => ExclusionMethod::BySource,
|
||||
"parcels_by_order" => ExclusionMethod::ParcelsByOrder,
|
||||
"reset_and_reiterate" => ExclusionMethod::ResetAndReiterate,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2022 Lee Yingtong Li (RunasSudo)
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -280,7 +280,7 @@ impl STVOptions {
|
|||
surplus.into(),
|
||||
surplus_order.into(),
|
||||
if papers == "transferable" || papers == "subtract_nontransferable" { true } else { false },
|
||||
if papers == "subtract_nontransferable" { true } else { false },
|
||||
if papers == "assume_progress_total" || papers == "subtract_nontransferable" { true } else { false },
|
||||
exclusion.into(),
|
||||
meek_nz_exclusion,
|
||||
sample.into(),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,62 @@
|
|||
Stage,1,,2,,3,,4,,5,,6,,7,,10,,11,,12,,13,,14,,15,,43,,48,,230,,231,,232,,233,,234,,235,,236,,254,
|
||||
Comment,First preferences,,"Surplus of WATT, Sheena",,"Surplus of MULHOLLAND, Evan",,"Surplus of RATNAM, Samantha",,"Exclusion of BRASSETT, Marcella",,"Exclusion of BRASSETT, Marcella",,"Exclusion of BRASSETT, Marcella",,"Exclusion of YOLCU, Berke",,"Exclusion of PULLEN, Linda",,"Exclusion of PULLEN, Linda",,"Exclusion of PULLEN, Linda",,"Exclusion of PULLEN, Linda",,"Exclusion of PULLEN, Linda",,"Exclusion of CONSIDINE, Matthew",,"Exclusion of MCCAMISH, Scott",,"Exclusion of MORAN, Kelly",,"Exclusion of GUEST, Owen",,"Exclusion of GUEST, Owen",,"Exclusion of GUEST, Owen",,"Exclusion of GUEST, Owen",,"Exclusion of GUEST, Owen",,"Surplus of ERDOGAN, Enver",,"Exclusion of SMALL, Jerome",
|
||||
"HIRMIZ, Imad",11326,H,11332,H,11340,H,11340,H,11340,H,11340,H,11340,H,11340,H,11340,H,11340,H,11340,H,11340,H,11340,H,11346,H,11347,H,21199,H,21252,H,25368,H,25368,H,25391,H,25391,H,25391,H,0,EX
|
||||
"LOWRY, Denise",320,H,320,H,321,H,321,H,321,H,321,H,321,H,322,H,322,H,322,H,322,H,322,H,322,H,325,H,327,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"MULHOLLAND, Evan",83448,EL,83448,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL
|
||||
"GUEST, Owen",692,H,698,H,8639,H,8639,H,8639,H,8639,H,8639,H,8640,H,8642,H,8642,H,8642,H,8642,H,8642,H,8645,H,8648,H,15707,H,,EX,,EX,,EX,,EX,0,EX,0,EX,0,EX
|
||||
"STAKER-GUNN, Tim",209,H,209,H,214,H,214,H,214,H,214,H,214,H,214,H,215,H,215,H,215,H,215,H,215,H,219,H,220,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"TEMPANY, Melinda",598,H,599,H,603,H,603,H,603,H,603,H,603,H,603,H,603,H,603,H,603,H,603,H,603,H,609,H,609,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"QADEER, Hafiz",412,H,414,H,417,H,417,H,417,H,417,H,417,H,417,H,417,H,417,H,417,H,417,H,417,H,420,H,421,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"DIAMANTOPOULOS, Georgia",1835,H,1837,H,1843,H,1843,H,1843,H,1843,H,1843,H,1843,H,1844,H,1844,H,1844,H,1844,H,1844,H,1845,H,1848,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"RACO, Francesco",129,H,131,H,134,H,134,H,134,H,134,H,134,H,134,H,134,H,134,H,134,H,134,H,134,H,137,H,140,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"ROS, Amita",1250,H,1252,H,1259,H,1259,H,1259,H,1259,H,1259,H,1259,H,1259,H,1259,H,1259,H,1259,H,1259,H,1261,H,1263,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"SINGH, Pushpinder",109,H,110,H,112,H,112,H,112,H,112,H,112,H,112,H,113,H,113,H,113,H,113,H,113,H,114,H,116,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"BHINDER, Vikram",97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,97,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"MORAN, Kelly",5510,H,5511,H,5521,H,5521,H,5521,H,5521,H,5521,H,5521,H,5523,H,5523,H,5523,H,5523,H,5523,H,5530,H,5557,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"MCCAMISH, Scott",91,H,91,H,93,H,93,H,93,H,93,H,93,H,93,H,94,H,94,H,94,H,94,H,94,H,97,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"RICHARDSON, Damien",4829,H,4830,H,4835,H,4835,H,4835,H,4835,H,4835,H,4836,H,4838,H,4838,H,4838,H,4838,H,4838,H,4846,H,4853,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"STODDART, Cameron",108,H,108,H,108,H,108,H,108,H,108,H,108,H,109,H,109,H,109,H,109,H,109,H,109,H,115,H,120,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"SILVERBERG, Paul",5424,H,5429,H,5438,H,5438,H,5438,H,5438,H,5438,H,5438,H,5440,H,5440,H,5440,H,5440,H,5440,H,5440,H,5447,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"VERSTEEGEN, Rachel",188,H,189,H,190,H,190,H,191,H,191,H,191,H,191,H,192,H,192,H,192,H,192,H,192,H,198,H,201,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"PHILPOTT-SMART, Simone",4671,H,4681,H,4685,H,4686,H,4686,H,4686,H,4686,H,4686,H,4686,H,4686,H,4686,H,4686,H,4686,H,4693,H,4696,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"STANFIELD, Thomas",102,H,103,H,104,H,104,H,104,H,104,H,104,H,104,H,105,H,105,H,105,H,105,H,105,H,113,H,119,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"PRIDHAM, Alison",1431,H,1436,H,1436,H,1438,H,1438,H,1438,H,1438,H,1438,H,1440,H,1440,H,1440,H,1440,H,1440,H,1463,H,1463,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"BUDGEON, Daryl",49,H,49,H,49,H,49,H,49,H,49,H,49,H,49,H,51,H,51,H,51,H,51,H,51,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"TAGGART, Lisa",1584,H,1586,H,1586,H,1586,H,1586,H,1586,H,1586,H,1586,H,1588,H,1588,H,1588,H,1588,H,1588,H,1608,H,1611,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"BRODIE, Gabrielle",58,H,59,H,59,H,59,H,59,H,59,H,59,H,59,H,64,H,64,H,64,H,64,H,64,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"GRUTZNER, Pauline",1543,H,1545,H,1545,H,1545,H,1545,H,1545,H,1545,H,1545,H,1550,H,1550,H,1550,H,1550,H,1550,H,1558,H,1559,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"PULLEN, Linda",39,H,39,H,39,H,39,H,39,H,39,H,39,H,40,H,,EX,,EX,,EX,,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"SOMYUREK, Adem",21510,H,21522,H,21525,H,21528,H,21528,H,21528,H,21528,H,21529,H,21529,H,21529,H,21529,H,21529,H,21529,H,21532,H,21532,H,41543,H,41595,H,43054,H,43054,H,50826,H,50826,H,50826,H,73381,H
|
||||
"de WIT, Cary",174,H,176,H,176,H,176,H,176,H,176,H,176,H,176,H,176,H,176,H,176,H,176,H,176,H,177,H,177,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"HORSFALL, Leah",6166,H,6202,H,6202,H,6213,H,6214,H,6214,H,6214,H,6214,H,6217,H,6218,H,6218,H,6218,H,6218,H,6222,H,6225,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"POON, Bruce",154,H,155,H,155,H,155,H,155,H,155,H,155,H,155,H,155,H,155,H,155,H,155,H,155,H,156,H,157,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"RATNAM, Samantha",81014,EL,81014,EL,81014,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL
|
||||
"KENNEDY, Esther",850,H,888,H,888,H,6182,H,6182,H,6182,H,6182,H,6182,H,6182,H,6182,H,6182,H,6182,H,6182,H,6193,H,6194,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"JEFFORD, Sarah",863,H,879,H,879,H,931,H,931,H,931,H,931,H,931,H,932,H,932,H,932,H,932,H,932,H,940,H,940,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"LEACH, Michael",685,H,699,H,699,H,722,H,723,H,723,H,723,H,723,H,723,H,723,H,723,H,723,H,723,H,725,H,725,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"MORRISON, Kenna",715,H,724,H,724,H,765,H,765,H,765,H,765,H,765,H,765,H,765,H,765,H,765,H,765,H,773,H,773,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"CONSTANTINOU, Ethan",3413,H,3417,H,3418,H,3418,H,3418,H,3418,H,3418,H,3418,H,3418,H,3418,H,3418,H,3418,H,3418,H,3464,H,3465,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"PODGER, Ben",57,H,58,H,58,H,58,H,58,H,58,H,58,H,59,H,59,H,59,H,59,H,59,H,59,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"WATT, Sheena",148830,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL,75406,EL
|
||||
"ERDOGAN, Enver",445,H,72685,H,72685,H,72691,H,72691,H,72691,H,72691,H,72694,H,72695,H,72695,H,72695,H,72695,H,72695,H,72697,H,72698,H,75389,H,75404,H,75448,EL,75448,EL,75448,EL,75448,EL,75406,EL,75406,EL
|
||||
"BYERS, Susie",734,H,976,H,976,H,980,H,980,H,980,H,980,H,980,H,980,H,980,H,980,H,980,H,980,H,988,H,989,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"GAUL, Chloe",709,H,1011,H,1011,H,1018,H,1018,H,1018,H,1018,H,1019,H,1019,H,1019,H,1019,H,1019,H,1019,H,1025,H,1025,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"ALJALIL, Ramy",344,H,362,H,362,H,363,H,363,H,363,H,363,H,363,H,363,H,363,H,363,H,363,H,363,H,364,H,364,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"FREEMAN, Nickee",1146,H,1150,H,1151,H,1151,H,1151,H,1151,H,1151,H,1152,H,1152,H,1152,H,1152,H,1152,H,1152,H,1179,H,1180,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"CASHION, Jake",40,H,40,H,40,H,40,H,40,H,40,H,40,H,41,H,41,H,41,H,41,H,41,H,41,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"PATTEN, Fiona",16117,H,16413,H,16415,H,16506,H,16514,H,16514,H,16514,H,16514,H,16514,H,16514,H,16514,H,16514,H,16514,H,16541,H,16542,H,23244,H,23303,H,23357,H,23358,H,23370,H,23371,H,23411,H,61557,H
|
||||
"RYAN, Judy",74,H,75,H,75,H,75,H,76,H,76,H,76,H,76,H,76,H,76,H,76,H,76,H,76,H,106,H,107,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"CLARK, Jenn",53,H,53,H,53,H,53,H,53,H,53,H,53,H,53,H,53,H,53,H,53,H,53,H,53,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"BRASSETT, Marcella",17,H,17,H,17,H,17,H,,EX,,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"JAGIELSKI, Tali Siani",61,H,61,H,61,H,61,H,64,H,64,H,64,H,64,H,64,H,64,H,64,H,64,H,64,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"YESILAGAC, Hatice",2678,H,2678,H,2678,H,2678,H,2678,H,2678,H,2678,H,2692,H,2692,H,2692,H,2692,H,2692,H,2692,H,2698,H,2699,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"YOLCU, Berke",33,H,33,H,33,H,33,H,33,H,33,H,33,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"HALE, Andrew",13508,H,13535,H,13535,H,13542,H,13542,H,13542,H,13542,H,13543,H,13544,H,13544,H,13544,H,13544,H,13544,H,13554,H,13554,H,15826,H,15856,H,15909,H,15909,H,15915,H,15915,H,15915,H,0,EX
|
||||
"THOMPSON, Renee",314,H,323,H,323,H,326,H,327,H,327,H,327,H,329,H,330,H,330,H,330,H,330,H,330,H,342,H,344,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"DAVIS, Jessica",4175,H,4175,H,4180,H,4180,H,4180,H,4180,H,4180,H,4181,H,4181,H,4181,H,4181,H,4181,H,4181,H,4227,H,4227,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"CONSIDINE, Matthew",76,H,77,H,77,H,77,H,77,H,77,H,77,H,78,H,78,H,78,H,78,H,78,H,78,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"SMALL, Jerome",20298,H,20357,H,20357,H,20393,H,20394,H,20394,H,20394,H,20395,H,20397,H,20397,H,20397,H,20397,H,20397,H,20407,H,20408,H,27988,H,27999,H,28020,H,28020,H,28022,H,28022,H,28022,H,0,EX
|
||||
"LEWIS, Cathy",1007,H,1012,H,1012,H,1018,H,1018,H,1018,H,1018,H,1018,H,1018,H,1018,H,1018,H,1018,H,1018,H,1026,H,1026,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
"MANCELL, Colin John",118,H,118,H,118,H,118,H,118,H,118,H,118,H,118,H,118,H,118,H,118,H,118,H,118,H,120,H,120,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX
|
||||
Loss by fraction,0,,36,,54,,74,,,,,,74,,74,,,,,,,,,,74,,77,,79,,161,,,,,,,,,,150,,151,,114,
|
||||
Exhausted,0,,0,,0,,0,,0,,0,,0,,0,,0,,0,,0,,0,,0,,0,,0,,5155,,5627,,6929,,6941,,7086,,7089,,7090,,15754,
|
|
Binary file not shown.
|
@ -0,0 +1,173 @@
|
|||
# Comment: 2008 Western Australia state election - ATL votes and partial reconstruction of some BTL votes - Western Australia STV
|
||||
# Source: https://www.elections.wa.gov.au/sites/default/files/content/documents/2008_SGE_Results_Stats_Part5.pdf, https://www.elections.wa.gov.au/elections/state/sgelection#/sg2008/region/01/results
|
||||
# Contributor: RunasSudo
|
||||
28 6
|
||||
# ATL
|
||||
7562 1 2 11 12 25 28 27 24 26 9 10 16 19 20 13 14 15 17 18 21 22 23 8 7 6 5 4 3 0 # A - Family First
|
||||
110821 3 4 5 6 7 8 21 22 23 26 27 24 28 1 2 11 12 13 14 15 16 17 18 19 20 9 10 25 0 # B - Australian Labor Party
|
||||
349 9 10 15 14 13 27 16 17 18 19 20 25 26 24 28 23 22 21 8 7 6 5 4 3 2 1 11 12 0 # C - Citizens Electoral Council
|
||||
7480 11 12 27 1 2 25 24 13 14 16 15 17 18 19 20 26 28 9 10 3 4 5 6 7 8 21 22 23 0 # D - Christian Democratic Party WA
|
||||
102138 13 14 15 16 17 18 11 12 19 20 1 2 24 27 26 28 21 22 23 9 10 3 4 5 6 7 8 25 0 # E - Liberal
|
||||
2331 19 20 11 12 1 2 25 13 14 15 16 17 18 24 26 27 3 4 5 6 7 8 21 22 23 9 10 28 0 # F - The Nationals
|
||||
29265 21 22 23 28 24 3 4 5 6 7 8 1 2 19 20 25 26 27 13 14 15 16 17 18 9 10 11 12 0 # G - Greens (WA)
|
||||
1425 24 19 20 4 8 17 12 21 22 23 27 26 28 11 7 6 5 3 18 16 15 14 13 2 1 25 10 9 0 # H - Independent
|
||||
1828 25 11 12 1 2 26 19 20 28 9 10 27 13 14 15 16 17 18 21 22 23 24 3 4 5 6 7 8 0 # I - One Nation
|
||||
429 26 6 7 8 27 24 28 25 21 22 23 3 4 5 9 10 19 20 13 14 15 16 17 18 1 2 11 12 0 # J - Independent
|
||||
192 27 11 12 1 2 25 19 20 9 10 3 4 5 6 7 8 13 14 15 16 17 18 26 24 21 22 23 28 0 # K - Independent
|
||||
1409 28 21 22 23 13 14 15 16 17 18 1 2 9 10 24 26 27 11 12 3 4 5 6 7 8 19 20 25 0 # L - Daylight Saving Party
|
||||
# BTL
|
||||
1140 1 0
|
||||
137 2 0
|
||||
36 3 1 0
|
||||
24 3 2 0
|
||||
6 3 4 1 0
|
||||
1 3 4 2 0
|
||||
954 3 4 5 0
|
||||
19 3 4 6 0
|
||||
7 3 4 7 0
|
||||
5 3 4 8 0
|
||||
1 3 4 17 0
|
||||
4 3 4 21 0
|
||||
104 3 5 0
|
||||
33 3 6 0
|
||||
22 3 7 0
|
||||
41 3 8 0
|
||||
2 3 9 0
|
||||
1 3 10 7 0
|
||||
3 3 11 0
|
||||
1 3 17 0
|
||||
1 3 18 0
|
||||
2 3 19 0
|
||||
12 3 21 0
|
||||
2 3 22 0
|
||||
1 3 28 0
|
||||
37 4 1 0
|
||||
25 4 2 0
|
||||
299 4 5 0
|
||||
42 4 6 0
|
||||
47 4 7 0
|
||||
31 4 8 0
|
||||
3 4 9 0
|
||||
1 4 10 1 0
|
||||
1 4 10 20 0
|
||||
2 4 11 0
|
||||
1 4 12 0
|
||||
2 4 15 0
|
||||
5 4 16 0
|
||||
1 4 19 0
|
||||
18 4 21 0
|
||||
3 4 22 0
|
||||
7 4 23 0
|
||||
1 4 25 0
|
||||
1 4 26 0
|
||||
2 4 27 0
|
||||
4 4 28 0
|
||||
368 5 0
|
||||
212 6 0
|
||||
227 7 0
|
||||
243 8 0
|
||||
47 9 0
|
||||
2 10 1 0
|
||||
1 10 5 0
|
||||
1 10 6 0
|
||||
1 10 8 0
|
||||
9 10 9 0
|
||||
1 10 11 0
|
||||
1 10 15 0
|
||||
1 10 19 0
|
||||
1 10 21 0
|
||||
1 10 23 0
|
||||
2 10 27 0
|
||||
514 11 0
|
||||
100 12 0
|
||||
17 13 1 0
|
||||
1 13 2 0
|
||||
2 13 5 0
|
||||
4 13 8 0
|
||||
4 13 9 0
|
||||
1 13 10 18 0
|
||||
5 13 11 0
|
||||
1 13 12 0
|
||||
4 13 14 1 0
|
||||
1 13 14 5 0
|
||||
1 13 14 6 0
|
||||
1 13 14 7 0
|
||||
3 13 14 11 0
|
||||
1 13 14 12 0
|
||||
1057 13 14 15 0
|
||||
20 13 14 16 0
|
||||
3 13 14 17 0
|
||||
6 13 14 18 0
|
||||
4 13 14 19 0
|
||||
4 13 14 21 0
|
||||
57 13 15 0
|
||||
38 13 16 0
|
||||
11 13 17 0
|
||||
22 13 18 0
|
||||
9 13 19 0
|
||||
1 13 20 0
|
||||
3 13 21 0
|
||||
1 13 22 0
|
||||
1 13 24 0
|
||||
3 13 28 0
|
||||
9 14 1 0
|
||||
1 14 7 0
|
||||
1 14 8 0
|
||||
1 14 9 0
|
||||
1 14 10 1 0
|
||||
3 14 11 0
|
||||
7 14 12 0
|
||||
68 14 15 0
|
||||
15 14 16 0
|
||||
9 14 17 0
|
||||
10 14 18 0
|
||||
4 14 19 0
|
||||
1 14 20 0
|
||||
3 14 21 0
|
||||
1 14 25 0
|
||||
2 14 28 0
|
||||
201 15 0
|
||||
234 16 0
|
||||
85 17 0
|
||||
305 18 0
|
||||
315 19 0
|
||||
44 20 0
|
||||
2379 21 0
|
||||
284 22 0
|
||||
300 23 0
|
||||
299 24 0
|
||||
223 25 0
|
||||
85 26 0
|
||||
106 27 0
|
||||
256 28 0
|
||||
9319 0
|
||||
0
|
||||
"BOLT, Stephen Charles" # 1 - Family First
|
||||
"HOPKINSON, Symia Joyce" # 2
|
||||
"FERGUSON, John Rilday" # 3 - Australian Labor Party
|
||||
"RAVLICH, Ljiljanna Maria" # 4
|
||||
"SAVAGE, Linda Rosmary" # 5
|
||||
"CARSON, Gary John" # 6
|
||||
"BURTON, Carolyn Anne" # 7
|
||||
"COMRIE, Craig Hugh John" # 8
|
||||
"VINCENT, Neil Allen" # 9 - Citizens Electoral Council
|
||||
"PASSMORE, Theresa" # 10
|
||||
"RANDALL, Dwight Allan" # 11 - Christian Democratic Party WA
|
||||
"GOIRAN, Gerard Pierre" # 12
|
||||
"MORTON, Helen Margaret" # 13 - Liberal
|
||||
"FARAGHER, Donna Evelyn Mary" # 14
|
||||
"HAYDEN, Alyssa Kathleen" # 15
|
||||
"BLIZARD, Stephen Michael" # 16
|
||||
"TREASE, Darryl Raymond" # 17
|
||||
"SIMPSON, Guy Julian" # 18
|
||||
"WOOD, Sean Damian" # 19 - The Nationals
|
||||
"MANGINI, Kevin Leonard Raymond" # 20
|
||||
"XAMON, Alison Marie" # 21 - Greens (WA)
|
||||
"WOLFF, Stephen Karl" # 22
|
||||
"DOUGLAS-MEYER, Damian Paul" # 23
|
||||
"HOYER, Thomas Harry John" # 24 - Independent
|
||||
"HOPKINSON, James Peter" # 25 - One Nation
|
||||
"NASH, Richard Paul" # 26 - Independent
|
||||
"TUCAK, John Damien" # 27 - Independent
|
||||
"DAY, Conor Patrick" # 28 - Daylight Saving Party
|
||||
"WA 2008 State General Election East Metropolitan Region"
|
|
@ -0,0 +1,32 @@
|
|||
Stage:,1,,2,,3,,4,,5,,6,,7,,8,,9,,10,
|
||||
Comment:,First preferences,,"Surplus of FERGUSON, John Rilday",,"Surplus of MORTON, Helen Margaret",,"Surplus of RAVLICH, Ljiljanna Maria",,"Surplus of FARAGHER, Donna Evelyn Mary",,"Exclusion of PASSMORE, Theresa",,"Exclusion of PASSMORE, Theresa",,"Exclusion of PASSMORE, Theresa",,"Exclusion of PASSMORE, Theresa",,"Exclusion of PASSMORE, Theresa",
|
||||
"BOLT, Stephen Charles",8702,H,8725,H,8735,H,8752,H,8755,H,8757,H,8757,H,8757,H,8757,H,8757,H
|
||||
"HOPKINSON, Symia Joyce",137,H,152,H,152,H,163,H,163,H,163,H,163,H,163,H,163,H,163,H
|
||||
"FERGUSON, John Rilday",112103,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL
|
||||
"RAVLICH, Ljiljanna Maria",533,H,72937,EL,72937,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL
|
||||
"SAVAGE, Linda Rosmary",368,H,435,H,436,H,33739,H,33739,H,33740,H,33740,H,33740,H,33740,H,33740,H
|
||||
"CARSON, Gary John",212,H,233,H,233,H,257,H,257,H,258,H,258,H,258,H,258,H,258,H
|
||||
"BURTON, Carolyn Anne",227,H,241,H,241,H,264,H,264,H,264,H,264,H,264,H,264,H,264,H
|
||||
"COMRIE, Craig Hugh John",243,H,269,H,271,H,286,H,286,H,287,H,287,H,287,H,287,H,287,H
|
||||
"VINCENT, Neil Allen",396,H,397,H,399,H,400,H,400,H,409,H,409,H,409,H,409,H,409,H
|
||||
"PASSMORE, Theresa",21,H,21,H,21,H,21,H,21,H,,EX,,EX,,EX,,EX,0,EX
|
||||
"RANDALL, Dwight Allan",7994,H,7995,H,7998,H,7998,H,7999,H,8000,H,8000,H,8000,H,8000,H,8000,H
|
||||
"GOIRAN, Gerard Pierre",100,H,100,H,100,H,100,H,102,H,102,H,102,H,102,H,102,H,102,H
|
||||
"MORTON, Helen Margaret",103424,EL,103424,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL
|
||||
"FARAGHER, Donna Evelyn Mary",136,H,136,H,63934,EL,63934,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL,39514,EL
|
||||
"HAYDEN, Alyssa Kathleen",201,H,201,H,236,H,236,H,24617,H,24618,H,24618,H,24618,H,24618,H,24618,H
|
||||
"BLIZARD, Stephen Michael",234,H,234,H,257,H,259,H,268,H,268,H,268,H,268,H,268,H,268,H
|
||||
"TREASE, Darryl Raymond",85,H,85,H,91,H,91,H,94,H,94,H,94,H,94,H,94,H,94,H
|
||||
"SIMPSON, Guy Julian",305,H,305,H,318,H,318,H,322,H,322,H,322,H,322,H,322,H,322,H
|
||||
"WOOD, Sean Damian",2646,H,2647,H,2652,H,2652,H,2653,H,2654,H,2654,H,2654,H,2654,H,2654,H
|
||||
"MANGINI, Kevin Leonard Raymond",44,H,44,H,44,H,44,H,44,H,44,H,44,H,44,H,44,H,44,H
|
||||
"XAMON, Alison Marie",31644,H,31651,H,31652,H,31661,H,31662,H,31663,H,31663,H,31663,H,31663,H,31663,H
|
||||
"WOLFF, Stephen Karl",284,H,285,H,285,H,286,H,286,H,286,H,286,H,286,H,286,H,286,H
|
||||
"DOUGLAS-MEYER, Damian Paul",300,H,300,H,300,H,303,H,303,H,304,H,304,H,304,H,304,H,304,H
|
||||
"HOYER, Thomas Harry John",1724,H,1724,H,1724,H,1724,H,1724,H,1724,H,1724,H,1724,H,1724,H,1724,H
|
||||
"HOPKINSON, James Peter",2051,H,2051,H,2051,H,2051,H,2051,H,2051,H,2051,H,2051,H,2051,H,2051,H
|
||||
"NASH, Richard Paul",514,H,514,H,514,H,514,H,514,H,514,H,514,H,514,H,514,H,514,H
|
||||
"TUCAK, John Damien",298,H,298,H,298,H,298,H,298,H,300,H,300,H,300,H,300,H,300,H
|
||||
"DAY, Conor Patrick",1665,H,1665,H,1666,H,1667,H,1667,H,1667,H,1667,H,1667,H,1667,H,1667,H
|
||||
Exhausted,9319,,9319,,9319,,9319,,9319,,9319,,9319,,9319,,9319,,9319,
|
||||
Loss by fraction,0,,8,,18,,31,,46,,,,,,,,,,46,
|
|
Binary file not shown.
|
@ -32,4 +32,5 @@ mod nswlg;
|
|||
mod prsa;
|
||||
mod scotland;
|
||||
mod special_cases;
|
||||
mod vec;
|
||||
mod vs_prsa_count;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2022 Lee Yingtong Li (RunasSudo)
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -33,10 +33,10 @@ fn nswlg_albury21_rational() {
|
|||
.ties(vec![TieStrategy::Backwards, TieStrategy::Random(String::from("20220322"))])
|
||||
.surplus_order(stv::SurplusOrder::ByOrder)
|
||||
.transferable_only(true)
|
||||
.subtract_nontransferable(true)
|
||||
.surplus_assume_total(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 0 --round-quota 0 --round-subtransfers by_parcel --quota-criterion geq --ties backwards random --random-seed 20220322 --surplus-order by_order --transferable-only --subtract-nontransferable");
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 0 --round-quota 0 --round-subtransfers by_parcel --quota-criterion geq --ties backwards random --random-seed 20220322 --surplus-order by_order --transferable-only --surplus-assume-total");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/City_of_Albury-finalpreferencedatafile.csv", "tests/data/City_of_Albury-finalpreferencedatafile.blt", stv_opts, None, &[]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use opentally::numbers::Rational;
|
||||
use opentally::stv;
|
||||
use opentally::ties::TieStrategy;
|
||||
|
||||
#[test]
|
||||
fn vec_nmet22_rational() {
|
||||
let stv_opts = stv::STVOptionsBuilder::default()
|
||||
.round_votes(Some(0))
|
||||
.round_quota(Some(0))
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.ties(vec![TieStrategy::Backwards])
|
||||
.surplus(stv::SurplusMethod::UIG)
|
||||
.surplus_order(stv::SurplusOrder::ByOrder)
|
||||
.exclusion(stv::ExclusionMethod::FirstPreferencesThenByValue)
|
||||
.early_bulk_elect(false)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 0 --round-quota 0 --quota-criterion geq --ties backwards --surplus uig --surplus-order by_order --exclusion first_prefs_then_by_value --no-early-bulk-elect");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/SE2022_NMET.csv", "tests/data/SE2022_NMET.blt", stv_opts, None, &["lbf", "exhausted"]);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* OpenTally: Open-source election vote counting
|
||||
* Copyright © 2021–2023 Lee Yingtong Li (RunasSudo)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Compare results under Western Australia STV with official results from WA Electoral Commission
|
||||
// Using (partially) reconstructed ballot papers
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use opentally::numbers::Rational;
|
||||
use opentally::stv;
|
||||
|
||||
#[test]
|
||||
fn wa_eastmetro08_rational() {
|
||||
// Validates only up to stage 10 (Exclusion of PASSMORE, Theresa)
|
||||
|
||||
let stv_opts = stv::STVOptionsBuilder::default()
|
||||
.round_votes(Some(0))
|
||||
.round_quota(Some(0))
|
||||
.round_subtransfers(stv::RoundSubtransfersMode::ByParcel)
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.exclusion(stv::ExclusionMethod::ParcelsByOrder)
|
||||
.surplus_order(stv::SurplusOrder::ByOrder)
|
||||
.surplus_assume_total(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 0 --round-quota 0 --round-subtransfers by_parcel --quota-criterion geq --ties backwards random --random-seed 20220322 --surplus-order by_order --surplus-assume-total --exclusion parcels_by_order");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/WA2008-EastMetro-PartialReconstruction.csv", "tests/data/WA2008-EastMetro-PartialReconstruction.blt", stv_opts, None, &["exhausted", "lbf"]);
|
||||
}
|
Loading…
Reference in New Issue