2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,10 +1,13 @@
Given a weighted one bit generator of random numbers where the probability of a one occuring, <math>P_1</math>, is not the same as <math>P_0</math>, the probability of a zero occuring, the probability of the occurrence of a one followed by a zero is <math>P_1</math> × <math>P_0</math>. This is the same as the probability of a zero followed by a one: <math>P_0</math> × <math>P_1</math>.
'''Task Details'''
;Task details:
* Use your language's random number generator to create a function/method/subroutine/... '''randN''' that returns a one or a zero, but with one occurring, on average, 1 out of N times, where N is an integer from the range 3 to 6 inclusive.
* Create a function '''unbiased''' that uses only randN as its source of randomness to become an unbiased generator of random ones and zeroes.
* For N over its range, generate and show counts of the outputs of randN and unbiased(randN).
<br>
The actual unbiasing should be done by generating two numbers at a time from randN and only returning a 1 or 0 if they are different. As long as you always return the first number or always return the second number, the probabilities discussed above should take over the biased probability of randN.
This task is an implementation of [http://en.wikipedia.org/wiki/Randomness_extractor#Von_Neumann_extractor Von Neumann debiasing], first described in a 1951 paper.
<br><br>

View file

@ -1,9 +1,6 @@
defmodule Random do
def init() do
:random.seed(:erlang.now)
end
def randN(n) do
if :random.uniform(n) == 1, do: 1, else: 0
if :rand.uniform(n) == 1, do: 1, else: 0
end
def unbiased(n) do
{x, y} = {randN(n), randN(n)}
@ -12,9 +9,9 @@ defmodule Random do
end
IO.puts "N biased unbiased"
Random.init
m = 10000
for n <- 3..6 do
xs = for _ <- 1..10000, do: Random.randN(n)
ys = for _ <- 1..10000, do: Random.unbiased(n)
IO.puts "#{n} #{Enum.sum(xs) / Enum.count(xs)} #{Enum.sum(ys) / Enum.count(ys)}"
xs = for _ <- 1..m, do: Random.randN(n)
ys = for _ <- 1..m, do: Random.unbiased(n)
IO.puts "#{n} #{Enum.sum(xs) / m} #{Enum.sum(ys) / m}"
end

View file

@ -0,0 +1,6 @@
import Control.Monad.Random
import Control.Monad
import Text.Printf
randN :: MonadRandom m => Int -> m Int
randN n = fromList [(0, fromIntegral n-1), (1, 1)]

View file

@ -0,0 +1,4 @@
unbiased :: (MonadRandom m, Eq x) => m x -> m x
unbiased g = do x <- g
y <- g
if x /= y then return y else unbiased g

View file

@ -0,0 +1,8 @@
main = forM_ [3..6] showCounts
where
showCounts b = do
r1 <- counts (randN b)
r2 <- counts (unbiased (randN b))
printf "n = %d biased: %d%% unbiased: %d%%\n" b r1 r2
counts g = (`div` 100) . length . filter (== 1) <$> replicateM 10000 g

View file

@ -1,29 +0,0 @@
import Control.Monad
import Random
import Data.IORef
import Text.Printf
randN :: Integer -> IO Bool
randN n = randomRIO (1,n) >>= return . (== 1)
unbiased :: Integer -> IO Bool
unbiased n = do
a <- randN n
b <- randN n
if a /= b then return a else unbiased n
main :: IO ()
main = forM_ [3..6] $ \n -> do
cb <- newIORef 0
cu <- newIORef 0
replicateM_ trials $ do
b <- randN n
u <- unbiased n
when b $ modifyIORef cb (+ 1)
when u $ modifyIORef cu (+ 1)
tb <- readIORef cb
tu <- readIORef cu
printf "%d: %5.2f%% %5.2f%%\n" n
(100 * fromIntegral tb / fromIntegral trials :: Double)
(100 * fromIntegral tu / fromIntegral trials :: Double)
where trials = 50000

View file

@ -16,5 +16,5 @@ for 3 .. 6 -> $n {
@fixed[ unbiased($n) ]++;
}
printf "N=%d randN: %s, %4.1f%% unbiased: %s, %4.1f%%\n",
$n, map { .perl, .[1] * 100 / $iterations }, $(@raw), $(@fixed);
$n, map { .perl, .[1] * 100 / $iterations }, @raw, @fixed;
}

View file

@ -0,0 +1,15 @@
function randN ( [int]$N )
{
[int]( ( Get-Random -Maximum $N ) -eq 0 )
}
function unbiased ( [int]$N )
{
do {
$X = randN $N
$Y = randN $N
}
While ( $X -eq $Y )
return $X
}

View file

@ -0,0 +1,15 @@
$Tests = 1000
ForEach ( $N in 3..6 )
{
$Biased = 0
$Unbiased = 0
ForEach ( $Test in 1..$Tests )
{
$Biased += randN $N
$Unbiased += unbiased $N
}
[pscustomobject]@{ N = $N
"Biased Ones out of $Test" = $Biased
"Unbiased Ones out of $Test" = $Unbiased }
}

View file

@ -1,21 +1,20 @@
/*REXX program generates unbiased random numbers and displays the results. */
parse arg # R seed . /*get optional parameters from the CL. */
if #=='' | #==',' then #=1000 /*# the number of SAMPLES to be used.*/
if R=='' | R==',' then R=6 /*R the high number for the range. */
if seed\=='' then call random ,,seed /*Not specified? Use for RANDOM seed. */
w=12; pad=left('',5) /*width of columnar output; indentation*/
dash=''; @b='biased'; @ub='un'@b /*literals for the SAY column headers. */
say pad c('N',5) c(@b) c(@b'%') c(@ub) c(@ub"%") c('samples') /*6 col header.*/
/*REXX program generates unbiased random numbers and displays the results to terminal.*/
parse arg # R seed . /*get optional parameters from the CL. */
if #=='' | #=="," then #=1000 /*# the number of SAMPLES to be used.*/
if R=='' | R=="," then R=6 /*R the high number for the range. */
if datatype(seed, 'W') then call random ,,seed /*Not specified? Use for RANDOM seed. */
w=12; pad=left('',5) /*width of columnar output; indentation*/
dash=''; @b="biased"; @ub='un'@b /*literals for the SAY column headers. */
say pad c('N',5) c(@b) c(@b'%') c(@ub) c(@ub"%") c('samples') /*six column header.*/
dash=
do N=3 to R; b=0; u=0; do j=1 for #
b=b+randN(N)
u=u+unbiased()
end /*j*/
do N=3 to R; b=0; u=0; do j=1 for #; b=b+randN(N)
u=u+unbiased()
end /*j*/
say pad c(N,5) c(b) pct(b) c(u) pct(u) c(#)
end /*N*/
exit /*stick a fork in it, we're all done. */
/*───────────────────────────────────one─liner subroutines────────────────────*/
c: return center(arg(1), word(arg(2) w,1), left(dash,1))
pct: return c(format(arg(1)/#*100,,2)'%') /*2 decimal digs.*/
randN: parse arg z; return random(1,z)==z
unbiased: do until x\==randN(N); x=randN(N); end; return x
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
c: return center( arg(1), word(arg(2) w, 1), left(dash, 1) )
pct: return c( format(arg(1) / # * 100, , 2)'%' ) /*two decimal digits.*/
randN: parse arg z; return random(1, z)==z
unbiased: do until x\==randN(N); x=randN(N); end /*until*/; return x