module Utils.Sampling where

import Utils.SemanticEditors
import Control.Arrow
import Control.Monad
import Data.List
import Utils.List
import Utils.MonadRandom
import Utils.Shuffle

-- This module is for separating sampling from MonadRandom in hopes of some day replacing it with
-- the standard version.

-- Uniform probability selection
selectRandom n l = replicateM n $ fromNonWeightedList l

-- Stochastic universal sampling
-- Results are randomized order
doSUS no weightedList = do
    x <- getRandomR (0,1) -- random spin
    doShuffle (sus weightedList no x)

sus :: [(Double,a)] -> Int -> Double -> [a]
sus elements no offsetRatio = sus' pts es []  
 where
    offset = offsetRatio*armSpan
    armSpan = totalWeight/fromIntegral no
    es = ((inzip first (scanl1 (+)).cycle.sortBy (comparing (negate.fst)))  elements)
    pts = [min totalWeight (offset+i) | i <- take no [0,armSpan..]]
    totalWeight = sum.map fst $ elements

sus' [] _ acc = acc
sus' a@(p:pts) r@((w,e):es) acc 
    | p <= w  = sus' pts r  (e:acc)
    | p > w  = sus' a es acc
    | otherwise = sus' pts r acc