#选择 #统计 #随机 #适应度 #算法 #生成 #测试

proportionate_selector

通过比例选择算法选择有用的解决方案进行重组

3 个版本

0.1.2 2022年9月6日
0.1.1 2022年9月5日
0.1.0 2022年9月5日

算法 中排名 1275

MIT 许可证

23KB
244

比例选择

proportionate_selector 允许在运行时从经验离散分布中进行采样。每个样本独立生成,且与先前生成的或未来的样本没有耦合。这允许从某些已知的离散分布中快速、可靠地生成样本。

用例

  • 多变量 A/B 测试
  • 游戏中的简单宝箱生成
  • 在进化算法中的应用
  • 帮助内容推广
  • 优惠券码生成
  • 等等...

示例

假设我们想根据与奖励收集品相关的某些稀有度来构建 非常简单 的宝箱奖励收集品。并且我们希望在运行时能够修改这些收集品的 稀有度(可能有数千种可能的物品)。

例如,

奖励物品 稀有度 发生概率(1/稀有度)
奖励 A 50 (1/50) = 0.02
奖励 B 10 (1/10) = 0.10
奖励 C 10 (1/10) = 0.10
奖励 D 2 (1/2) = 0.5
无奖励 3.5714 (1/3.5714) = 0.28

注意:proportionate_selector 要求概率之和等于 1。由于某些原因,您正在使用不同的排名方法,您可以在使用 proportionate_selector 之前对概率进行归一化。在大多数情况下,您都应该这样做。

use proportionate_selector::*;

#[derive(PartialEq, Debug)]
pub struct LootboxItem {
    pub id: i32,
    /// Likelihood of recieve item from lootbox.
    /// Rarity represents inverse lilihood of recieveing
    /// this item.
    ///
    /// e.g. rairity of 1, means lootbox item will be more
    /// frequently generated as opposed to rarity of 100.
    pub rarity: f64,
}

impl Probability for LootboxItem {
    fn prob(&self) -> f64 {
        // rarity is modeled as 1 out of X occurance, so
        // rarity of 20 has probability of 1/20.
        1.0 / self.rarity
    }
}

let endOfLevel1Box = vec![
    LootboxItem {id: 0, rarity: 50.0},   // 2%
    LootboxItem {id: 1, rarity: 10.0},   // 10%
    LootboxItem {id: 2, rarity: 10.0},   // 10%
    LootboxItem {id: 3, rarity: 2.0},    // 50%
    LootboxItem {id: 4, rarity: 3.5714}, // 28%
];

// create discrete distribution for sampling
let epdf = DiscreteDistribution::new(&endOfLevel1Box, SamplingMethod::Linear).unwrap();
let s = epdf.sample();

println!("{:?}", epdf.sample());

基准测试 (+/- 5%)

采样 时间 物品数量
线性 30 ns 100
线性 6 us 10,000
线性 486 us 1,000,000
Cdf 31 ns 100
Cdf 41 ns 10,000
Cdf 62 ns 1,000,000
随机 315 ns 100
随机 30 us 10,000
随机 40 us 1,000,000

基准测试运行在

  Model Name: Mac mini
  Model Identifier: Macmini9,1
  Chip: Apple M1
  Total Number of Cores: 8 (4 performance and 4 efficiency)
  Memory: 16 GB

开发

cargo build     # build
cargo test      # run tests
cargo doc       # generate docs
cargo criterion # benchmarks
cargo clippy    # linter

依赖项

~0.6–1.2MB
~25K SLoC