8 个不稳定版本 (3 个破坏性更新)
0.4.0 | 2024年7月3日 |
---|---|
0.3.0 | 2023年10月28日 |
0.2.0 | 2023年8月4日 |
0.1.4 | 2023年6月12日 |
0.1.1 | 2023年3月26日 |
在 数学 分类中排名第 144
每月下载量 32 次
350KB
9K SLoC
Rust 中单次可转让选票实现
此程序是 Rust 中单次可转让选票的实现。目标是提供可与其他选票计数软件(如 Droop.py)可重复的选票计数记录。
目前,只实现了 Meek 计数方法。
更多详情请参阅以下博客文章:STV-rs: Rust 中单次可转让选票实现。
用法
使用 Cargo
$ RUST_LOG=$LOG_LEVEL cargo run \
--release -- \
--arithmetic $ARITHMETIC \
--input ballots.txt \
meek \
--parallel=<true|false>
$ RUST_LOG=$LOG_LEVEL cargo run \
--release -- \
--arithmetic $ARITHMETIC \
--input ballots.txt \
meek \
--parallel=<true|false> \
--equalize
算术实现
您可以通过 --arithmetic
命令行标志来控制用于计票的算术。以下是一些可用的实现。
fixed9
:每个算术操作都四舍五入到9位小数。除非显式标记的操作(计算保留因子),否则向下舍入。这由 Rust 的i64
支持,因此可能会溢出。通过启用checked_i64
功能(默认启用)进行编译将捕获整数溢出并使程序崩溃,而不是继续使用错误的数据。bigfixed9
:与fixed9
相同,但这是由大整数类型(来自num
crate)支持的,因此不会溢出。然而,这比fixed9
慢。float64
:使用 64 位浮点算术(Rust 的f64
)。通常很快,但更脆弱,因为浮点算术引入的舍入意味着基本的属性,如 结合律 和 分配律 并不成立。exact
:使用不带舍入的精确有理数。通常计算复杂度太高,无法完成超过几轮。approx
:在每次 STV 轮次中使用精确有理数,但在每次轮次之后将 Meek 保留因子舍入,以避免计算复杂度爆炸。
均衡计数
在此模式下,对等排名的候选人名单的选票将尽可能公平地计数,通过模拟等排名候选人的所有可能排列的叠加。
例如,选票 a b=c
变成了 a b c
(权重 1/2)和 a c b
(权重 1/2)的叠加。同样,选票 a b=c=d
被计为 6 份选票的叠加,每份选票权重为 1/6:a b c d
,a b d c
,a c b d
,a c d b
,a d b c
,a d c b
。
日志级别
除了写入标准输出的选举记录(旨在与 Droop.py 保持一致以实现可重现性)之外,您还可以通过设置环境变量 $RUST_LOG
来获取更多详细信息。
日志级别将提供以下信息。
info
:打印高级结果:选举设置、当选/失败候选人。debug
:info
+ 打印每个 STV 轮次的调试信息。trace
:debug
+ 打印每个轮次中每个选票的计数方式。
有关更高级的日志控制,请参阅 env_logger
crate 文档。
并行处理
要加快计算速度,您可以通过命令行标志 --parallel
启用并行处理。
投票计数过程涉及对所有选票的投票进行累积,对每张选票的计数结果进行求和。没有并行处理时,这是通过简单的选票序列循环完成的。启用并行处理后,使用并行循环代替,其中每张选票在任意线程上独立计数,求和可以在任何顺序中进行。
由于求和是在任意顺序下进行的,因此重要的是要使用加法是 可交换 和 可结合 的算术,否则结果将不可重现。这排除了 float64
,因为加法不是可结合的。
在底层,使用 rayon
crate 自动调度和分配工作到可用的 CPU 核心(map-reduce 架构)。
其他 STV 实现
以下是非详尽列表的 STV 实现。
贡献
有关详细信息,请参阅 CONTRIBUTING.md
。
许可
Apache 2.0;有关详细信息,请参阅 LICENSE
。
免责声明
本项目不是官方的 Google 项目。Google 不提供支持,并且 Google 明确排除对该项目的质量、适销性或特定用途的适用性的任何保证。
依赖关系
~6–8MB
~139K SLoC