June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -4,27 +4,30 @@ if trials=='' | trials=="," then trials=1000000 /*Not specified? Then use the
if digs=='' | digs=="," then digs=15 /* " " " " " " */
if datatype(seed, 'W') then call random ,,seed /*allows repeatability for RANDOM nums.*/
numeric digits digs /*use a specific number of decimal digs*/
names= 'aleph beth gimel daleth he waw zayin heth totals' /*names of cells.*/
#= words(names) - 1; s=0
HI=100000
do n=1 for #-1; prob.n=1 / (n+4); Hprob.n=prob.n * HI; s=s + prob.n
names= 'aleph beth gimel daleth he waw zayin heth totals' /*names of the cells.*/
HI=100000 /*max REXX RANDOM num*/
z=words(names); #=z - 1 /*#≡the number of actual/useable names.*/
$=0 /*initialize sum of the probabilities. */
do n=1 for #; prob.n=1 / (n+4); if n==# then prob.n= 1759 / 27720
$=$ + prob.n; Hprob.n=prob.n * HI
end /*n*/
!.=0
prob.#=1759/27720; !.9=trials; Hprob.#=prob.# * HI; s=s + prob.#
prob.9=s
do j=1 for trials; r=random(1, HI) /*generate X number of random numbers.*/
prob.z=$ /*define the value of the ───totals───.*/
@.=0 /*initialize all counters in the range.*/
@.z=trials /*define the last counter of " " */
do j=1 for trials; r=random(HI) /*gen TRIAL number of random numbers.*/
do k=1 for # /*for each cell, compute percentages. */
if r<=Hprob.k then !.k=!.k + 1 /* " " " range, bump the counter*/
if r<=Hprob.k then @.k=@.k + 1 /* " " " range, bump the counter*/
end /*k*/
end /*j*/
@= '' /*@: a literal used for CENTER BIF pad*/
w=digs +6 /*W: display width for the percentages*/
_= '' /*_: a literal used for CENTER BIF pad*/
w=digs + 6 /*W: display width for the percentages*/
d=4 + max( length(trials), length('count') ) /* [↓] display a formatted top header.*/
say center('name',15,@) center('count',d,@) center('target %',w,@) center('actual %',w,@)
say center('name',15,_) center('count',d,_) center('target %',w,_) center('actual %',w,_)
do i=1 for #+1 /*display each of the cells and totals.*/
say ' ' left( word(names, i), 13) right(!.i, d-2) " ",
left( format( prob.i * 100, d), w-2),
left( format( !.i/trials * 100, d), w-2)
if i==# then say center(@,15,@) center(@,d,@) center(@,w,@) center(@,w,@)
end /*i*/ /*stick a fork in it, we are all done.*/
do cell=1 for z /*display each of the cells and totals.*/
say ' ' left( word(names, cell), 13) right(@.cell, d-2) " ",
left( format( prob.cell * 100, d), w-2),
left( format( @.cell/trials * 100, d), w-2)
if cell==# then say center(_,15,_) center(_,d,_) center(_,w,_) center(_,w,_)
end /*c*/ /* [↑] display a formatted foot header*/
/*stick a fork in it, we are all done.*/

View file

@ -0,0 +1,25 @@
# Project : Probabilistic choice
# Date : 2017/10/01
# Author : Gal Zsolt (~ CalmoSoft ~)
# Email : <calmosoft@gmail.com>
cnt = list(8)
item = ["aleph","beth","gimel","daleth","he","waw","zayin","heth"]
prob = [1/5.0, 1/6.0, 1/7.0, 1/8.0, 1/9.0, 1/10.0, 1/11.0, 1759/27720]
for trial = 1 to 1000000
r = random(10)/10
p = 0
for i = 1 to len(prob)
p = p + prob[i]
if r < p
cnt[i] = cnt[i] + 1
loop
ok
next
next
see "item actual theoretical" + nl
for i = 1 to len(item)
see "" + item[i] + " " + cnt[i]/1000000 + " " + prob[i] + nl
next

View file

@ -0,0 +1,127 @@
extern crate rand;
use rand::distributions::{IndependentSample, Sample, Weighted, WeightedChoice};
use rand::{weak_rng, Rng};
const DATA: [(&str, f64); 8] = [
("aleph", 1.0 / 5.0),
("beth", 1.0 / 6.0),
("gimel", 1.0 / 7.0),
("daleth", 1.0 / 8.0),
("he", 1.0 / 9.0),
("waw", 1.0 / 10.0),
("zayin", 1.0 / 11.0),
("heth", 1759.0 / 27720.0),
];
const SAMPLES: usize = 1_000_000;
/// Generate a mapping to be used by `WeightedChoice`
fn gen_mapping() -> Vec<Weighted<usize>> {
DATA.iter()
.enumerate()
.map(|(i, &(_, p))| Weighted {
// `WeightedChoice` requires `u32` weights rather than raw probabilities. For each
// probability, we convert it to a `u32` weight, and associate it with an index. We
// multiply by a constant because small numbers such as 0.2 when casted to `u32`
// become `0`. This conversion decreases the accuracy of the mapping, which is why we
// provide an implementation which uses `f64`s for the best accuracy.
weight: (p * 1_000_000_000.0) as u32,
item: i,
})
.collect()
}
/// Generate a mapping of the raw probabilities
fn gen_mapping_float() -> Vec<f64> {
// This does the work of `WeightedChoice::new`, splitting a number into various ranges. The
// `item` of `Weighted` is represented here merely by the probability's position in the `Vec`.
let mut running_total = 0.0;
DATA.iter()
.map(|&(_, p)| {
running_total += p;
running_total
})
.collect()
}
/// An implementation of `WeightedChoice` which uses probabilities rather than weights. Refer to
/// the `WeightedChoice` source for serious usage.
struct WcFloat {
mapping: Vec<f64>,
}
impl WcFloat {
fn new(mapping: &[f64]) -> Self {
Self {
mapping: mapping.to_vec(),
}
}
// This is roughly the same logic as `WeightedChoice::ind_sample` (though is likely slower)
fn search(&self, sample_prob: f64) -> usize {
let idx = self.mapping
.binary_search_by(|p| p.partial_cmp(&sample_prob).unwrap());
match idx {
Ok(i) | Err(i) => i,
}
}
}
impl IndependentSample<usize> for WcFloat {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
// Because we know the total is exactly 1.0, we can merely use a raw float value.
// Otherwise caching `Range::new(0.0, running_total)` and sampling with
// `range.ind_sample(&mut rng)` is recommended.
let sample_prob = rng.next_f64();
self.search(sample_prob)
}
}
impl Sample<usize> for WcFloat {
fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
self.ind_sample(rng)
}
}
fn take_samples<R: Rng, T>(rng: &mut R, wc: &T) -> [usize; 8]
where
T: IndependentSample<usize>,
{
let mut counts = [0; 8];
for _ in 0..SAMPLES {
let sample = wc.ind_sample(rng);
counts[sample] += 1;
}
counts
}
fn print_mapping(counts: &[usize]) {
println!("Item | Expected | Actual ");
println!("-------+----------+----------");
for (&(name, expected), &count) in DATA.iter().zip(counts.iter()) {
let real = count as f64 / SAMPLES as f64;
println!("{:6} | {:.6} | {:.6}", name, expected, real);
}
}
fn main() {
let mut rng = weak_rng();
println!(" ~~~ U32 METHOD ~~~");
let mut mapping = gen_mapping();
let wc = WeightedChoice::new(&mut mapping);
let counts = take_samples(&mut rng, &wc);
print_mapping(&counts);
println!();
println!(" ~~~ FLOAT METHOD ~~~");
// initialize the float version of `WeightedChoice`
let mapping = gen_mapping_float();
let wc = WcFloat::new(&mapping);
let counts = take_samples(&mut rng, &wc);
print_mapping(&counts);
}

View file

@ -0,0 +1,8 @@
clear
mata
letters="aleph","beth","gimel","daleth","he","waw","zayin","heth"
a=letters[rdiscrete(10000,1,(1/5,1/6,1/7,1/8,1/9,1/10,1/11,1759/27720))]'
st_addobs(10000)
st_addvar("str10","a")
st_sstore(.,.,a)
end