GithubHelp home page GithubHelp logo

titsuki / raku-random-choice Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 31 KB

A Raku alias method implementation

License: Artistic License 2.0

Raku 100.00%
alias method raku rakulang perl6 random choice zef

raku-random-choice's Introduction

Build Status

NAME

Random::Choice - A Raku alias method implementation

SYNOPSIS

use Random::Choice;

say choice(:size(8), :p([0.1, 0.1, 0.1, 0.7])); # (3 1 0 3 3 3 3 3)
say choice(:p([0.1, 0.1, 0.1, 0.7])); # 3

DESCRIPTION

Random::Choice is a Raku alias method implementation. Alias method is an efficient algorithm for sampling from a discrete probability distribution.

METHODS

choice

Defined as:

multi sub choice(:@p! --> Int) is export
multi sub choice(Int :$size!, :@p! --> List)

Returns a sample which is an Int value or a List. Where :@p is the probabilities associated with each index and :$size is the sample size.

FAQ

Is Random::Choice faster than Mix.roll?

The answer is YES when you roll a large biased dice or try to roll a dice many times; but NO when a biased dice is small or try to roll a dice few times.

Why? There are some possible reasons:

  • Random::Choice employs O(N) + O(1) algorithm whereas Mix.roll employs O(N) + O(N) algorithm (rakudo 2018.12).

  • Mix.roll is directly written in nqp. In general, nqp-powered code is faster than naive-Raku-powered code when they take small input.

  • Both algorithms take O(N) initialization cost; however, the actual cost of Mix.roll is slightly less than Random::Choice.

A benchmark result is here (For more info, see example/bench.p6):

A Benchmark Result

benchmark result

The Comparison Table on the Benchmark

$ perl6 example/bench.p6 
Benchmark: 
Timing 1000 iterations of Mix(size=10, @p.elems=10) , Random::Choice(size=10, @p.elems=10)...
Mix(size=10, @p.elems=10) : 0.076 wallclock secs (0.086 usr 0.003 sys 0.089 cpu) @ 13154.606/s (n=1000)
Random::Choice(size=10, @p.elems=10): 0.122 wallclock secs (0.137 usr 0.008 sys 0.145 cpu) @ 8210.383/s (n=1000)
O--------------------------------------O---------O----------------------------O--------------------------------------O
|                                      | Rate    | Mix(size=10, @p.elems=10)  | Random::Choice(size=10, @p.elems=10) |
O======================================O=========O============================O======================================O
| Mix(size=10, @p.elems=10)            | 13155/s | --                         | -42%                                 |
| Random::Choice(size=10, @p.elems=10) | 8210/s  | 73%                        | --                                   |
O--------------------------------------O---------O----------------------------O--------------------------------------O
Benchmark: 
Timing 1000 iterations of Mix(size=1000, @p.elems=10) , Random::Choice(size=1000, @p.elems=10)...
Mix(size=1000, @p.elems=10) : 1.879 wallclock secs (1.892 usr 0.000 sys 1.892 cpu) @ 532.130/s (n=1000)
Random::Choice(size=1000, @p.elems=10): 0.097 wallclock secs (0.099 usr 0.002 sys 0.101 cpu) @ 10361.621/s (n=1000)
O----------------------------------------O---------O------------------------------O----------------------------------------O
|                                        | Rate    | Mix(size=1000, @p.elems=10)  | Random::Choice(size=1000, @p.elems=10) |
O========================================O=========O==============================O========================================O
| Mix(size=1000, @p.elems=10)            | 532/s   | --                           | 2141%                                  |
| Random::Choice(size=1000, @p.elems=10) | 10362/s | -96%                         | --                                     |
O----------------------------------------O---------O------------------------------O----------------------------------------O
Benchmark: 
Timing 1000 iterations of Mix(size=10, @p.elems=1000) , Random::Choice(size=10, @p.elems=1000)...
Mix(size=10, @p.elems=1000) : 2.576 wallclock secs (2.560 usr 0.020 sys 2.580 cpu) @ 388.182/s (n=1000)
Random::Choice(size=10, @p.elems=1000): 6.010 wallclock secs (6.015 usr 0.032 sys 6.047 cpu) @ 166.398/s (n=1000)
O----------------------------------------O-------O------------------------------O----------------------------------------O
|                                        | Rate  | Mix(size=10, @p.elems=1000)  | Random::Choice(size=10, @p.elems=1000) |
O========================================O=======O==============================O========================================O
| Mix(size=10, @p.elems=1000)            | 388/s | --                           | -57%                                   |
| Random::Choice(size=10, @p.elems=1000) | 166/s | 134%                         | --                                     |
O----------------------------------------O-------O------------------------------O----------------------------------------O
Benchmark: 
Timing 1000 iterations of Mix(size=100, @p.elems=100), Random::Choice(size=100, @p.elems=100)...
Mix(size=100, @p.elems=100): 1.505 wallclock secs (1.511 usr 0.000 sys 1.511 cpu) @ 664.420/s (n=1000)
Random::Choice(size=100, @p.elems=100): 0.619 wallclock secs (0.624 usr 0.000 sys 0.624 cpu) @ 1616.535/s (n=1000)
O----------------------------------------O--------O-----------------------------O----------------------------------------O
|                                        | Rate   | Mix(size=100, @p.elems=100) | Random::Choice(size=100, @p.elems=100) |
O========================================O========O=============================O========================================O
| Mix(size=100, @p.elems=100)            | 664/s  | --                          | 146%                                   |
| Random::Choice(size=100, @p.elems=100) | 1617/s | -59%                        | --                                     |
O----------------------------------------O--------O-----------------------------O----------------------------------------O
Benchmark: 
Timing 1000 iterations of Mix(size=1000, @p.elems=1000), Random::Choice(size=1000, @p.elems=1000)...
Mix(size=1000, @p.elems=1000): 135.720 wallclock secs (135.946 usr 0.288 sys 136.234 cpu) @ 7.368/s (n=1000)
Random::Choice(size=1000, @p.elems=1000): 6.022 wallclock secs (6.031 usr 0.028 sys 6.058 cpu) @ 166.058/s (n=1000)
O------------------------------------------O--------O-------------------------------O------------------------------------------O
|                                          | Rate   | Mix(size=1000, @p.elems=1000) | Random::Choice(size=1000, @p.elems=1000) |
O==========================================O========O===============================O==========================================O
| Mix(size=1000, @p.elems=1000)            | 7.37/s | --                            | 2158%                                    |
| Random::Choice(size=1000, @p.elems=1000) | 166/s  | -96%                          | --                                       |
O------------------------------------------O--------O-------------------------------O------------------------------------------O

The Environment on the Benchmark

  • CPU Ryzen7 5800X (8core)

  • OS Debian11 bullseye

AUTHOR

titsuki [email protected]

COPYRIGHT AND LICENSE

Copyright 2019 titsuki

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

The algorithm is from:

  • Vose, Michael D. "A linear algorithm for generating random numbers with a given distribution." IEEE Transactions on software engineering 17.9 (1991): 972-975.

raku-random-choice's People

Stargazers

 avatar

Watchers

 avatar  avatar

raku-random-choice's Issues

Suggestion: Comparison of weighted roll in README

Calling .roll on a Bag or Mix will do a weighted random selection. See Baggy.roll.

A simplified choice function might look something like this

sub choice(:$size where *1 = 1, :@p where abs(1 - .sum) < 1e-3) {
    @p.pairs.Mix.roll($size)
}

say choice(:size(5), :p([0.1, 0.1, 0.1, 0.7]));

I'm not a stats guy, so I don't know if the distributions would be comparable to your module.

Perhaps your README could be updated to state any advantages or disadvantages over the above approach, particularly given that the above approve is faster than your module.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.