Rename --round-tvs to --round-surplus-fractions and --round-weights to --round-values
This commit is contained in:
parent
77fe5effb2
commit
6da51837a5
|
@ -159,7 +159,7 @@ In the BLT file format, each set of preferences can have a specified weight –
|
|||
|
||||
When ballots are not normalised (default), a set of preferences with weight *n* > 1 is represented as a single ballot with value *n*. This is known as [list-packed ballots](http://www.votingmatters.org.uk/ISSUE21/I21P1.pdf).
|
||||
|
||||
When ballots are normalised, a set of preferences with weight *n* > 1 is instead converted to *n* ballots each with value 1. This is generally required only when the rules directly deal with individual ballot weights, such as when *Sum surplus transfers* is set to *Per ballot*.
|
||||
When ballots are normalised, a set of preferences with weight *n* > 1 is instead converted to *n* ballots each with value 1. This is generally required only when the rules directly deal with individual ballot values, such as when *Sum surplus transfers* is set to *Per ballot*.
|
||||
|
||||
## Count optimisations
|
||||
|
||||
|
@ -167,15 +167,15 @@ When ballots are normalised, a set of preferences with weight *n* > 1 is instead
|
|||
|
||||
When early bulk election is enabled (default), the count terminates as soon as the set of winning candidates is known. Specifically:
|
||||
|
||||
* At the beginning of each stage, if the number of not-excluded candidates exactly equals the number of vacancies to fill, all remaining candidates are declared elected in a single stage. This is typical of most STV rules.
|
||||
* If a proposed exclusion would cause the number of not-excluded candidates to exactly equal the number of vacancies, all remaining candidates are declared elected without transfers arising from the proposed exclusion being performed.
|
||||
* At the end of any stage, if *n* vacancies remain and the *n*-th top continuing candidate has more votes than all lower continuing candidates (plus votes awaiting transfer), the *n* top continuing candidate are immediately declared elected.
|
||||
* At the beginning of each stage, if the number of continuing candidates exactly equals the number of remaining vacancies, all continuing candidates are declared elected in a single stage. This is typical of most STV rules.
|
||||
* If a proposed exclusion would cause the number of continuing candidates to exactly equal the number of remaining vacancies, all other continuing candidates are declared elected without transfers arising from the proposed exclusion being performed.
|
||||
* At the end of any stage, if *n* vacancies remain and the *n*-th top continuing candidate has more votes than all lower continuing candidates (plus votes awaiting transfer), the *n* top continuing candidates are immediately declared elected.
|
||||
|
||||
If an early bulk election is performed, further surplus distributions are not performed, and outstanding exclusions, if any, are not completed, even if they could change the order of election.
|
||||
|
||||
When early bulk election is disabled, surpluses continue to be distributed, and outstanding exclusions continue to be completed, even once the number of not-excluded candidates exactly equals the number of vacancies to fill. Bulk election is performed only as a final measure once there are no more surpluses to distribute, and no exclusions to complete.
|
||||
When early bulk election is disabled, surpluses continue to be distributed, and outstanding exclusions continue to be completed, even once the number of continuing candidates exactly equals the number of remaining vacancies. Bulk election is performed only as a final measure once there are no more surpluses to distribute, and no exclusions to complete.
|
||||
|
||||
In either case, candidates are declared elected in descending order of votes. This ensures that only one candidate is ever elected at a time and the order of election is well-defined, which is required e.g. for some affirmative action rules.
|
||||
In either case, candidates are declared elected in descending order of votes. This ensures that only one candidate is ever elected at a time and the order of election is well-defined, which is required e.g. for affirmative action rules.
|
||||
|
||||
Note that the OpenTally rules for early bulk election are aggressive, and many STV rules do not implement all 3 (if any at all). It is not possible at this time to selectively apply only some of the rules. In order to reproduce the result of a count performed by others, where not all rules were implemented, consider disabling early bulk election and comparing the results at the time a bulk election would have been made.
|
||||
|
||||
|
@ -202,23 +202,23 @@ When *Surplus method* is set to *Meek method*, this option controls when candida
|
|||
|
||||
## Rounding
|
||||
|
||||
### Round quota/votes/surplus fractions/ballot weights to [n] d.p. (--round-quota, --round-votes, --round-tvs, --round-weights)
|
||||
### Round quota/votes/surplus fractions/ballot values to [n] d.p. (--round-quota, --round-votes, --round-surplus-fractions, --round-values)
|
||||
|
||||
When rounding is enabled, the specified values are rounded to the specified number of decimal places. This enables, for example, votes to be counted only in integers, while ballot weights and surplus fractions are calculated to higher precision (according to the *Numbers* option).
|
||||
When rounding is enabled, the specified values are rounded to the specified number of decimal places. This enables, for example, votes to be counted only in integers, while ballot values and surplus fractions are calculated to higher precision (according to the *Numbers* option).
|
||||
|
||||
When enabled, the quota is incremented or rounded up (according to the *Quota* option), whereas votes, surplus fractions and weights are always rounded down.
|
||||
When enabled, the quota is incremented or rounded up (according to the *Quota* option), whereas votes, surplus fractions and ballot values are always rounded down.
|
||||
|
||||
In relation to *Round surplus fractions to [n] d.p.* (--round-tvs) – note that surplus fractions are used in STV in calculations of the form *A* × (*B*/*C*), where (*B*/*C*) is the surplus fraction. The order of operations depends on this setting:
|
||||
|
||||
* When this option is disabled (default), (*A* × *B*) is calculated first, then divided by *C*. This minimises rounding errors.
|
||||
* When this option is enabled, (*B*/*C*) is calculated separately first and rounded to the specified precision, before being multiplied by *A*. Many STV rules designed for hand counting prescribe this method of manipulating surplus fractions.
|
||||
|
||||
In Australia, surplus fractions are often known as ‘transfer values’; however, the term ‘value’ is reserved in OpenTally for referring to the values of votes.
|
||||
Surplus fractions are often known as ‘transfer values’; however, the term ‘value’ is reserved in OpenTally for referring to the values of votes.
|
||||
|
||||
When *Surplus method* is set to *Meek method*:
|
||||
|
||||
* --round-weights instead controls the rounding of candidate keep values
|
||||
* --round-tvs instead controls the rounding of each intermediate product when computing candidates' votes
|
||||
* --round-values instead controls the rounding of candidate keep values
|
||||
* --round-surplus-fractions instead controls the rounding of each intermediate product when computing candidates' votes
|
||||
* --round-votes controls the rounding of the final number of votes credited to each candidate
|
||||
|
||||
### (Gregory) Sum surplus transfers (--sum-surplus-transfers)
|
||||
|
|
|
@ -235,21 +235,21 @@
|
|||
</div>
|
||||
<div class="col-6">
|
||||
<label>
|
||||
<input type="checkbox" id="chkRoundTVs">
|
||||
<input type="checkbox" id="chkRoundSFs">
|
||||
Surplus fractions:
|
||||
</label>
|
||||
<label>
|
||||
<input type="number" id="txtRoundTVs" value="0" min="0" style="width: 3em;">
|
||||
<input type="number" id="txtRoundSFs" value="0" min="0" style="width: 3em;">
|
||||
d.p.
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label>
|
||||
<input type="checkbox" id="chkRoundWeights">
|
||||
Ballot weights:
|
||||
<input type="checkbox" id="chkRoundValues">
|
||||
Ballot values:
|
||||
</label>
|
||||
<label>
|
||||
<input type="number" id="txtRoundWeights" value="0" min="0" style="width: 3em;">
|
||||
<input type="number" id="txtRoundValues" value="0" min="0" style="width: 3em;">
|
||||
d.p.
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -132,8 +132,8 @@ async function clickCount() {
|
|||
|
||||
// Init STV options
|
||||
let optsStr = [
|
||||
document.getElementById('chkRoundTVs').checked ? parseInt(document.getElementById('txtRoundTVs').value) : null,
|
||||
document.getElementById('chkRoundWeights').checked ? parseInt(document.getElementById('txtRoundWeights').value) : null,
|
||||
document.getElementById('chkRoundSFs').checked ? parseInt(document.getElementById('txtRoundSFs').value) : null,
|
||||
document.getElementById('chkRoundValues').checked ? parseInt(document.getElementById('txtRoundValues').value) : null,
|
||||
document.getElementById('chkRoundVotes').checked ? parseInt(document.getElementById('txtRoundVotes').value) : null,
|
||||
document.getElementById('chkRoundQuota').checked ? parseInt(document.getElementById('txtRoundQuota').value) : null,
|
||||
document.getElementById('selSumTransfers').value,
|
||||
|
@ -370,8 +370,8 @@ function changePreset() {
|
|||
document.getElementById('chkNormaliseBallots').checked = false;
|
||||
document.getElementById('chkRoundQuota').checked = false;
|
||||
document.getElementById('chkRoundVotes').checked = false;
|
||||
document.getElementById('chkRoundTVs').checked = false;
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'wig';
|
||||
|
@ -392,9 +392,9 @@ function changePreset() {
|
|||
document.getElementById('chkRoundQuota').checked = true;
|
||||
document.getElementById('txtRoundQuota').value = '0';
|
||||
document.getElementById('chkRoundVotes').checked = false;
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '5';
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '5';
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'per_ballot';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'wig';
|
||||
|
@ -416,8 +416,8 @@ function changePreset() {
|
|||
document.getElementById('chkNormaliseBallots').checked = false;
|
||||
document.getElementById('chkRoundQuota').checked = false;
|
||||
document.getElementById('chkRoundVotes').checked = false;
|
||||
document.getElementById('chkRoundTVs').checked = false;
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
//document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('txtMeekSurplusTolerance').value = '0.001%';
|
||||
//document.getElementById('selSurplus').value = 'by_size';
|
||||
|
@ -442,10 +442,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '9';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '9';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '9';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '9';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '9';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '9';
|
||||
//document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('txtMeekSurplusTolerance').value = '0.0001';
|
||||
//document.getElementById('selSurplus').value = 'by_size';
|
||||
|
@ -470,10 +470,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '9';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '9';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '9';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '9';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '9';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '9';
|
||||
//document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('txtMeekSurplusTolerance').value = '0.0001';
|
||||
//document.getElementById('selSurplus').value = 'by_size';
|
||||
|
@ -495,8 +495,8 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '0';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '0';
|
||||
document.getElementById('chkRoundTVs').checked = false;
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_order';
|
||||
document.getElementById('selTransfers').value = 'uig';
|
||||
|
@ -517,8 +517,8 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '0';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '0';
|
||||
document.getElementById('chkRoundTVs').checked = false;
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'by_value';
|
||||
document.getElementById('selSurplus').value = 'by_order';
|
||||
document.getElementById('selTransfers').value = 'wig';
|
||||
|
@ -539,8 +539,8 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '0';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '6';
|
||||
document.getElementById('chkRoundTVs').checked = false;
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_order';
|
||||
document.getElementById('selTransfers').value = 'eg';
|
||||
|
@ -561,8 +561,8 @@ function changePreset() {
|
|||
document.getElementById('chkRoundQuota').checked = true;
|
||||
document.getElementById('txtRoundQuota').value = '0';
|
||||
document.getElementById('chkRoundVotes').checked = false;
|
||||
document.getElementById('chkRoundTVs').checked = false;
|
||||
document.getElementById('chkRoundWeights').checked = false;
|
||||
document.getElementById('chkRoundSFs').checked = false;
|
||||
document.getElementById('chkRoundValues').checked = false;
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'wig';
|
||||
|
@ -584,10 +584,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '3';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '3';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '3';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '3';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '3';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '3';
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_order';
|
||||
document.getElementById('selTransfers').value = 'eg';
|
||||
|
@ -609,10 +609,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '2';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '2';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '2';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '2';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '2';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '2';
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'eg';
|
||||
|
@ -634,10 +634,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '2';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '2';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '2';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '2';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '2';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '2';
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'eg';
|
||||
|
@ -659,10 +659,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '2';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '2';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '2';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '2';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '2';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '2';
|
||||
document.getElementById('selSumTransfers').value = 'single_step';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'eg';
|
||||
|
@ -684,10 +684,10 @@ function changePreset() {
|
|||
document.getElementById('txtRoundQuota').value = '2';
|
||||
document.getElementById('chkRoundVotes').checked = true;
|
||||
document.getElementById('txtRoundVotes').value = '2';
|
||||
document.getElementById('chkRoundTVs').checked = true;
|
||||
document.getElementById('txtRoundTVs').value = '2';
|
||||
document.getElementById('chkRoundWeights').checked = true;
|
||||
document.getElementById('txtRoundWeights').value = '2';
|
||||
document.getElementById('chkRoundSFs').checked = true;
|
||||
document.getElementById('txtRoundSFs').value = '2';
|
||||
document.getElementById('chkRoundValues').checked = true;
|
||||
document.getElementById('txtRoundValues').value = '2';
|
||||
document.getElementById('selSumTransfers').value = 'per_ballot';
|
||||
document.getElementById('selSurplus').value = 'by_size';
|
||||
document.getElementById('selTransfers').value = 'eg';
|
||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -68,13 +68,13 @@ struct STV {
|
|||
// -----------------------
|
||||
// -- Rounding settings --
|
||||
|
||||
/// Round transfer values to specified decimal places
|
||||
#[clap(help_heading=Some("ROUNDING"), long, value_name="dps")]
|
||||
round_tvs: Option<usize>,
|
||||
/// Round surplus fractions to specified decimal places
|
||||
#[clap(help_heading=Some("ROUNDING"), long, alias="round_tvs", value_name="dps")]
|
||||
round_surplus_fractions: Option<usize>,
|
||||
|
||||
/// Round ballot weights to specified decimal places
|
||||
#[clap(help_heading=Some("ROUNDING"), long, value_name="dps")]
|
||||
round_weights: Option<usize>,
|
||||
/// Round ballot values to specified decimal places
|
||||
#[clap(help_heading=Some("ROUNDING"), long, alias="round_weights", value_name="dps")]
|
||||
round_values: Option<usize>,
|
||||
|
||||
/// Round votes to specified decimal places
|
||||
#[clap(help_heading=Some("ROUNDING"), long, value_name="dps")]
|
||||
|
@ -253,8 +253,8 @@ where
|
|||
{
|
||||
// Copy applicable options
|
||||
let opts = STVOptions::new(
|
||||
cmd_opts.round_tvs,
|
||||
cmd_opts.round_weights,
|
||||
cmd_opts.round_surplus_fractions,
|
||||
cmd_opts.round_values,
|
||||
cmd_opts.round_votes,
|
||||
cmd_opts.round_quota,
|
||||
&cmd_opts.sum_surplus_transfers,
|
||||
|
|
|
@ -187,7 +187,7 @@ where
|
|||
SumSurplusTransfersMode::SingleStep => {
|
||||
// Calculate transfer across all votes
|
||||
//state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.dps$} votes.", entry.num_ballots, entry.num_votes, dps=opts.pp_decimals));
|
||||
return reweight_vote(&entry.num_votes, &entry.num_ballots, surplus, is_weighted, surplus_fraction, surplus_denom, opts.round_tvs, opts.round_votes);
|
||||
return reweight_vote(&entry.num_votes, &entry.num_ballots, surplus, is_weighted, surplus_fraction, surplus_denom, opts.round_surplus_fractions, opts.round_votes);
|
||||
}
|
||||
SumSurplusTransfersMode::ByValue => {
|
||||
// Sum transfers by value
|
||||
|
@ -204,7 +204,7 @@ where
|
|||
num_ballots += &vote.ballot.orig_value;
|
||||
}
|
||||
//state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.dps$} votes, received at value {:.dps2$}.", num_ballots, num_votes, value, dps=opts.pp_decimals, dps2=max(opts.pp_decimals, 2)));
|
||||
result += reweight_vote(&num_votes, &num_ballots, surplus, is_weighted, surplus_fraction, surplus_denom, opts.round_tvs, opts.round_votes);
|
||||
result += reweight_vote(&num_votes, &num_ballots, surplus, is_weighted, surplus_fraction, surplus_denom, opts.round_surplus_fractions, opts.round_votes);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -214,7 +214,7 @@ where
|
|||
// TODO: This could be moved to distribute_surplus to avoid looping over the votes and calculating transfer values twice
|
||||
let mut result = N::new();
|
||||
for vote in entry.votes.iter() {
|
||||
result += reweight_vote(&vote.value, &vote.ballot.orig_value, surplus, is_weighted, surplus_fraction, surplus_denom, opts.round_tvs, opts.round_votes);
|
||||
result += reweight_vote(&vote.value, &vote.ballot.orig_value, surplus, is_weighted, surplus_fraction, surplus_denom, opts.round_surplus_fractions, opts.round_votes);
|
||||
}
|
||||
//state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.dps$} votes.", entry.num_ballots, entry.num_votes, dps=opts.pp_decimals));
|
||||
return result;
|
||||
|
@ -270,7 +270,7 @@ where
|
|||
surplus_fraction = Some(surplus.clone() / v);
|
||||
|
||||
// Round down if requested
|
||||
if let Some(dps) = opts.round_tvs {
|
||||
if let Some(dps) = opts.round_surplus_fractions {
|
||||
surplus_fraction.as_mut().unwrap().floor_mut(dps);
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ where
|
|||
|
||||
// Reweight votes
|
||||
for vote in parcel.votes.iter_mut() {
|
||||
vote.value = reweight_vote(&vote.value, &vote.ballot.orig_value, &surplus, is_weighted, &surplus_fraction, &surplus_denom, opts.round_tvs, opts.round_weights);
|
||||
vote.value = reweight_vote(&vote.value, &vote.ballot.orig_value, &surplus, is_weighted, &surplus_fraction, &surplus_denom, opts.round_surplus_fractions, opts.round_values);
|
||||
}
|
||||
|
||||
count_card.parcels.push(parcel);
|
||||
|
|
|
@ -179,7 +179,7 @@ where
|
|||
count_card.votes += to_transfer;
|
||||
|
||||
let mut new_remaining_multiplier = &remaining_multiplier * &(N::one() - count_card.keep_value.as_ref().unwrap());
|
||||
if let Some(dps) = opts.round_tvs {
|
||||
if let Some(dps) = opts.round_surplus_fractions {
|
||||
new_remaining_multiplier.ceil_mut(dps);
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ fn recompute_keep_values<'s, N: Number>(state: &mut CountState<'s, N>, opts: &ST
|
|||
let count_card = state.candidates.get_mut(candidate).unwrap();
|
||||
count_card.keep_value = Some(count_card.keep_value.take().unwrap() * state.quota.as_ref().unwrap() / &count_card.votes);
|
||||
|
||||
if let Some(dps) = opts.round_weights {
|
||||
if let Some(dps) = opts.round_values {
|
||||
// NZ Meek STV rounds *up*!
|
||||
count_card.keep_value.as_mut().unwrap().ceil_mut(dps);
|
||||
}
|
||||
|
|
|
@ -41,10 +41,10 @@ use std::ops;
|
|||
|
||||
/// Options for conducting an STV count
|
||||
pub struct STVOptions {
|
||||
/// Round transfer values to specified decimal places
|
||||
pub round_tvs: Option<usize>,
|
||||
/// Round ballot weights to specified decimal places
|
||||
pub round_weights: Option<usize>,
|
||||
/// Round surplus fractions to specified decimal places
|
||||
pub round_surplus_fractions: Option<usize>,
|
||||
/// Round ballot values to specified decimal places
|
||||
pub round_values: Option<usize>,
|
||||
/// Round votes to specified decimal places
|
||||
pub round_votes: Option<usize>,
|
||||
/// Round quota to specified decimal places
|
||||
|
@ -96,8 +96,8 @@ pub struct STVOptions {
|
|||
impl STVOptions {
|
||||
/// Returns a new [STVOptions] based on arguments given as strings
|
||||
pub fn new(
|
||||
round_tvs: Option<usize>,
|
||||
round_weights: Option<usize>,
|
||||
round_surplus_fractions: Option<usize>,
|
||||
round_values: Option<usize>,
|
||||
round_votes: Option<usize>,
|
||||
round_quota: Option<usize>,
|
||||
sum_surplus_transfers: &str,
|
||||
|
@ -124,8 +124,8 @@ impl STVOptions {
|
|||
pp_decimals: usize,
|
||||
) -> Self {
|
||||
return STVOptions {
|
||||
round_tvs,
|
||||
round_weights,
|
||||
round_surplus_fractions,
|
||||
round_values,
|
||||
round_votes,
|
||||
round_quota,
|
||||
sum_surplus_transfers: match sum_surplus_transfers {
|
||||
|
@ -206,8 +206,8 @@ impl STVOptions {
|
|||
pub fn describe<N: Number>(&self) -> String {
|
||||
let mut flags = Vec::new();
|
||||
let n_str = N::describe_opt(); if !n_str.is_empty() { flags.push(N::describe_opt()) };
|
||||
if let Some(dps) = self.round_tvs { flags.push(format!("--round-tvs {}", dps)); }
|
||||
if let Some(dps) = self.round_weights { flags.push(format!("--round-weights {}", dps)); }
|
||||
if let Some(dps) = self.round_surplus_fractions { flags.push(format!("--round-tvs {}", dps)); }
|
||||
if let Some(dps) = self.round_values { flags.push(format!("--round-weights {}", dps)); }
|
||||
if let Some(dps) = self.round_votes { flags.push(format!("--round-votes {}", dps)); }
|
||||
if let Some(dps) = self.round_quota { flags.push(format!("--round-quota {}", dps)); }
|
||||
if self.surplus != SurplusMethod::Meek && self.sum_surplus_transfers != SumSurplusTransfersMode::SingleStep { flags.push(self.sum_surplus_transfers.describe()); }
|
||||
|
|
|
@ -211,8 +211,8 @@ pub struct STVOptions(stv::STVOptions);
|
|||
impl STVOptions {
|
||||
/// Wrapper for [stv::STVOptions::new]
|
||||
pub fn new(
|
||||
round_tvs: Option<usize>,
|
||||
round_weights: Option<usize>,
|
||||
round_surplus_fractions: Option<usize>,
|
||||
round_values: Option<usize>,
|
||||
round_votes: Option<usize>,
|
||||
round_quota: Option<usize>,
|
||||
sum_surplus_transfers: &str,
|
||||
|
@ -237,8 +237,8 @@ impl STVOptions {
|
|||
pp_decimals: usize,
|
||||
) -> Self {
|
||||
Self(stv::STVOptions::new(
|
||||
round_tvs,
|
||||
round_weights,
|
||||
round_surplus_fractions,
|
||||
round_values,
|
||||
round_votes,
|
||||
round_quota,
|
||||
sum_surplus_transfers,
|
||||
|
|
|
@ -23,8 +23,8 @@ use opentally::stv;
|
|||
#[test]
|
||||
fn act_kurrajong20_rational() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: None,
|
||||
round_weights: None,
|
||||
round_surplus_fractions: None,
|
||||
round_values: None,
|
||||
round_votes: Some(6),
|
||||
round_quota: Some(0),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -60,8 +60,8 @@ fn aec_tas19_rational() {
|
|||
}
|
||||
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: None,
|
||||
round_weights: None,
|
||||
round_surplus_fractions: None,
|
||||
round_values: None,
|
||||
round_votes: Some(0),
|
||||
round_quota: Some(0),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -39,8 +39,8 @@ fn prsa1_constr1_rational() {
|
|||
election.constraints = Some(Constraints::from_con(lines.map(|r| r.expect("IO Error").to_string()).into_iter()));
|
||||
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(3),
|
||||
round_weights: Some(3),
|
||||
round_surplus_fractions: Some(3),
|
||||
round_values: Some(3),
|
||||
round_votes: Some(3),
|
||||
round_quota: Some(3),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
@ -102,8 +102,8 @@ fn prsa1_constr2_rational() {
|
|||
election.constraints = Some(Constraints::from_con(lines.map(|r| r.expect("IO Error").to_string()).into_iter()));
|
||||
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(3),
|
||||
round_weights: Some(3),
|
||||
round_surplus_fractions: Some(3),
|
||||
round_values: Some(3),
|
||||
round_votes: Some(3),
|
||||
round_quota: Some(3),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
@ -165,8 +165,8 @@ fn prsa1_constr3_rational() {
|
|||
election.constraints = Some(Constraints::from_con(lines.map(|r| r.expect("IO Error").to_string()).into_iter()));
|
||||
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(3),
|
||||
round_weights: Some(3),
|
||||
round_surplus_fractions: Some(3),
|
||||
round_values: Some(3),
|
||||
round_votes: Some(3),
|
||||
round_quota: Some(3),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
@ -240,8 +240,8 @@ fn ers97_cantbulkexclude_rational() {
|
|||
election.constraints = Some(Constraints::from_con(lines.map(|r| r.expect("IO Error").to_string()).into_iter()));
|
||||
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(2),
|
||||
round_weights: Some(2),
|
||||
round_surplus_fractions: Some(2),
|
||||
round_values: Some(2),
|
||||
round_votes: Some(2),
|
||||
round_quota: Some(2),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -23,8 +23,8 @@ use opentally::stv;
|
|||
#[test]
|
||||
fn csm15_float64() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: None,
|
||||
round_weights: None,
|
||||
round_surplus_fractions: None,
|
||||
round_values: None,
|
||||
round_votes: None,
|
||||
round_quota: Some(0),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -23,8 +23,8 @@ use opentally::stv;
|
|||
#[test]
|
||||
fn ers97_rational() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(2),
|
||||
round_weights: Some(2),
|
||||
round_surplus_fractions: Some(2),
|
||||
round_values: Some(2),
|
||||
round_votes: Some(2),
|
||||
round_quota: Some(2),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -25,8 +25,8 @@ use opentally::stv;
|
|||
#[test]
|
||||
fn meek87_ers97_float64() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: None,
|
||||
round_weights: None,
|
||||
round_surplus_fractions: None,
|
||||
round_values: None,
|
||||
round_votes: None,
|
||||
round_quota: None,
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
@ -58,8 +58,8 @@ fn meek87_ers97_float64() {
|
|||
#[test]
|
||||
fn meek06_ers97_fixed12() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(9),
|
||||
round_weights: Some(9),
|
||||
round_surplus_fractions: Some(9),
|
||||
round_values: Some(9),
|
||||
round_votes: Some(9),
|
||||
round_quota: Some(9),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
@ -132,8 +132,8 @@ fn meek06_ers97_fixed12() {
|
|||
#[test]
|
||||
fn meeknz_ers97_fixed12() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(9),
|
||||
round_weights: Some(9),
|
||||
round_surplus_fractions: Some(9),
|
||||
round_values: Some(9),
|
||||
round_votes: Some(9),
|
||||
round_quota: Some(9),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -23,8 +23,8 @@ use opentally::stv;
|
|||
#[test]
|
||||
fn prsa1_rational() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(3),
|
||||
round_weights: Some(3),
|
||||
round_surplus_fractions: Some(3),
|
||||
round_values: Some(3),
|
||||
round_votes: Some(3),
|
||||
round_quota: Some(3),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep,
|
||||
|
|
|
@ -27,8 +27,8 @@ use std::ops;
|
|||
#[test]
|
||||
fn scotland_linn07_fixed5() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(5),
|
||||
round_weights: Some(5),
|
||||
round_surplus_fractions: Some(5),
|
||||
round_values: Some(5),
|
||||
round_votes: Some(5),
|
||||
round_quota: Some(0),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::PerBallot,
|
||||
|
@ -60,8 +60,8 @@ fn scotland_linn07_fixed5() {
|
|||
#[test]
|
||||
fn scotland_linn07_gfixed5() {
|
||||
let stv_opts = stv::STVOptions {
|
||||
round_tvs: Some(5),
|
||||
round_weights: Some(5),
|
||||
round_surplus_fractions: Some(5),
|
||||
round_values: Some(5),
|
||||
round_votes: Some(5),
|
||||
round_quota: Some(0),
|
||||
sum_surplus_transfers: stv::SumSurplusTransfersMode::PerBallot,
|
||||
|
|
Loading…
Reference in New Issue