-
Notifications
You must be signed in to change notification settings - Fork 0
/
exp-onlinePWS.hs
122 lines (100 loc) · 5.02 KB
/
exp-onlinePWS.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import Lotto
import Sample
import Utils
import Math.Combinat.Partitions
import Control.Monad.Primitive (PrimState, PrimMonad)
import Control.Monad (foldM, forM)
import Control.Applicative()
import System.Random.MWC (Gen, initialize)
import qualified Math.Combinatorics.Multiset as MS
import qualified Data.Vector as V
import qualified Data.Sequence as S
import Graphics.Gnuplot.Simple
import System.IO
import Statistics.Sample
allBlottoPartitionsWithoutZeros :: Int -> Int -> [[Int]]
allBlottoPartitionsWithoutZeros n m = map fromPartition (partitionsWithKParts m n) >>= MS.permutations . MS.fromList
filterSellers :: [Int] -> Int -> [[Int]] -> [[Int]]
filterSellers buyer delta = filter (all (\diff -> abs diff < delta) . zipWith (-) buyer)
sampleSellers :: PrimMonad m => [Int] -> [[Int]] -> Int -> Gen (PrimState m) -> m [[Int]]
sampleSellers buyer sellers size gen = do
sellersMin <- forM (zip [0..] buyer) (\(i, buyerBin) ->
randomElement (filter (\s -> s !! i <= buyerBin) sellers) gen
)
restSellers <- sample sellers (min (size - length sellersMin) (length sellers)) gen
return $ sellersMin ++ restSellers
-- reservationPartition :: [Int] -> [Int]
-- reservationPartition buyer = map p' buyer
-- where
-- n = sum buyer
-- p' p = floor (sqrt ((fromIntegral n - fromIntegral p) * fromIntegral p) :: Double)
data Stats = Stats { paid :: S.Seq Int, time :: Int }
emptyStats :: Int -> Stats
emptyStats m = Stats { paid = S.replicate m 0, time = 0 }
nextStats :: Stats -> [Int] -> [Int] -> Int -> Stats
nextStats currentStats buyer seller binIndex
| all (>0) currentPaid = currentStats
| S.index currentPaid binIndex == 0 && sellerBin <= buyerBin =
Stats { paid = S.update binIndex sellerBin currentPaid, time = time currentStats + 1 }
| otherwise =
Stats { paid = currentPaid, time = time currentStats + 1 }
where
sellerBin = seller !! binIndex
buyerBin = buyer !! binIndex
currentPaid = paid currentStats
main :: IO ()
main = do
let (n, m) = (49, 7)
buyer = uniform' n m
buyerR = map (+ 2) buyer
allPs = allBlottoPartitionsWithoutZeros n m
sellersBinDelta = 4
sellersCount = 200
suitableSellers = filterSellers buyer sellersBinDelta allPs
experimentsCount = 1000
allStats <- forM [0..experimentsCount] (\seed -> do
gen <- initialize (V.fromList [seed])
sellers <- sampleSellers buyerR suitableSellers sellersCount gen
let indices = [(sellerIndex, binIndex) | sellerIndex <- [0 .. length sellers - 1], binIndex <- [0 .. m - 1]]
shuffledIndices <- sample indices (length indices) gen
foldM (\st (si, bi) -> return $ nextStats st buyerR (sellers !! si) bi) (emptyStats m) shuffledIndices
)
let paidSums = map (sum . paid) allStats
times = map time allStats
-- Set Directory Output
setExperimentDir "onlinePWS"
-- Plot Stats
let paidSumsH = histogram paidSums
timesH = histogram times
plotTitle = "n = " ++ show n ++ ", m = " ++ show m
plotHistogram t title = plotPathStyle [t, Title plotTitle] PlotStyle {plotType=Boxes, lineSpec=CustomStyle [LineTitle title]}
plotHistogram (PNG "paidSums.png") "Cost Distribution" paidSumsH
plotHistogram (PNG "timesPassed.png") "Time Passed Distribution" timesH
-- plotHistogram (terminal (X11.persist X11.cons)) "Distance Max" hMax
-- Dump Log
_ <- withFile "log.txt" WriteMode (\h -> do
putStrLnBoth h "INPUT"
putStrLnBoth h $ "n = " ++ show n
putStrLnBoth h $ "m = " ++ show m
putStrLnBoth h $ "Buyer = " ++ show buyer
putStrLnBoth h $ "Buyer Threshold = " ++ show buyerR
putStrLnBoth h $ "Sellers Delta = " ++ show sellersBinDelta
putStrLnBoth h $ "Selected Sellers Count = " ++ show sellersCount
putStrLnBoth h $ "Runs Count = " ++ show experimentsCount
putStrLnBoth h ""
putStrLnBoth h "OUTPUT"
putStrLnBoth h $ "All Suitable Sellers Count = " ++ show (length suitableSellers)
putStrLnBoth h $ "Actual Sellers Count in Experiment = " ++ show (min (length suitableSellers) sellersCount)
putStrLnBoth h $ "Paid Sums Distribution: " ++ show paidSumsH
putStrLnBoth h $ "\tMean: " ++ show (mean (V.fromList (map fromIntegral paidSums)))
putStrLnBoth h $ "\tVariance: " ++ show (variance (V.fromList (map fromIntegral paidSums)))
putStrLnBoth h $ "\tSkewness: " ++ show (skewness (V.fromList (map fromIntegral paidSums)))
putStrLnBoth h $ "Time Passed Distribution: " ++ show timesH
putStrLnBoth h $ "\tMean: " ++ show (mean (V.fromList (map fromIntegral times)))
putStrLnBoth h $ "\tVariance: " ++ show (variance (V.fromList (map fromIntegral times)))
putStrLnBoth h $ "\tSkewness: " ++ show (skewness (V.fromList (map fromIntegral times)))
return ())
-- Save CSVs
saveCSV "paidSums.csv" ["paid", "count"] paidSumsH
saveCSV "timesPassed.csv" ["timePassed", "count"] paidSumsH
return ()