Skip to content

Commit c4e1771

Browse files
committed
initial commit
1 parent 7658c70 commit c4e1771

10 files changed

+714
-0
lines changed

CWSim.hs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
module Main where
2+
3+
import Sim
4+
import ChainDef
5+
import Distribution
6+
import Node
7+
import EventResult
8+
9+
_LAMBDA = 0.00234797779287925
10+
_MU = 0.01690544010873064
11+
12+
chainDef = do
13+
src <- createSource (Logged "Customer")
14+
sink <- createSink (Logged "Server") (ExpDistr _MU)
15+
trans src sink (ExpDistr _LAMBDA)
16+
17+
_DEADLINE = 10000000
18+
19+
simulation = flushAt _DEADLINE
20+
21+
main = do
22+
results <- runSimT simulation chainDef
23+
24+
let serverResults = reverse $ (map (\(EventResult _ _ t0 t1) -> (t0, t1)) . snd) (head results)
25+
print (length serverResults)
26+
let diffs = map (uncurry (flip (-))) serverResults
27+
let lol = map (\(a, (b, c)) -> (a, c - b)) . uncurry ($)
28+
. foldl (\(f, r) x -> let (g, r2) = insert 0 x r in (f . g, r2)) (id, []) $ serverResults
29+
let meanQueue = sum (map (\(a, b) -> fromIntegral a * b) lol) / _DEADLINE
30+
print meanQueue
31+
32+
type Queuey = (Integer, (Double, Double))
33+
34+
mean m = sum m / fromIntegral (length m)
35+
36+
insert :: Double -> (Double, Double) -> [Queuey] -> ([Queuey] -> [Queuey], [Queuey])
37+
insert z (s, b) [] = (((0, (z, s)) :), [(1, (s, b))])
38+
insert z (s, b) ((n, (s2, b2)) : rest) = if s > b2
39+
then let (f, rst) = insert b2 (s, b) rest in
40+
(((n, (s2, b2)) :) . f, rst)
41+
else
42+
(((n, (s2, s)) :), insertRest b b2 ((n, (s, b2)) : rest))
43+
where
44+
insertRest x l [] = [(1, (l, x))]
45+
insertRest x _ ((n, (s, b)) : rest) =
46+
if x < b then ((n + 1, (s, x)) : (n, (x, b)) : rest)
47+
else (n + 1, (s, b)) : insertRest x b rest

ChainDef.hs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving, RankNTypes #-}
2+
3+
module ChainDef where
4+
5+
import Node
6+
import Distribution
7+
8+
import Data.Map as Map
9+
import Control.Monad.State
10+
import Control.Monad.Identity
11+
12+
type Graph = Map.Map NodeId AnyNode
13+
14+
newtype ChainDef a = ChainDef { unChainDef :: StateT NodeId (StateT Graph Identity) a }
15+
deriving (Monad)
16+
17+
runChainDef :: ChainDef a -> (a, Graph)
18+
runChainDef = (\((a, _), b) -> (a, b))
19+
. runIdentity
20+
. flip runStateT Map.empty
21+
. flip runStateT 2 -- 0 and 1 reserved for source/sink
22+
. unChainDef
23+
24+
newId :: ChainDef NodeId
25+
newId = do
26+
ChainDef get >>= \n -> ChainDef (put (n + 1)) >> return n
27+
28+
getGraph :: ChainDef Graph
29+
getGraph = ChainDef (lift get)
30+
31+
putGraph :: Graph -> ChainDef ()
32+
putGraph = ChainDef . lift . put
33+
34+
trans :: (Distribution d, SrcNode src, DstNode dest) => src -> dest -> d -> ChainDef ()
35+
trans source target distr = do
36+
graph <- getGraph
37+
let newNode = addTrans (MkDestNode target, MkDistr distr) (MkSourceNode source)
38+
putGraph $ Map.insert (nodeId (nodeInfo newNode)) (toAny newNode) graph
39+
40+
createNode :: NodeClass n => (NodeId -> n) -> ChainDef n
41+
createNode newNode = do
42+
i <- newId
43+
graph <- getGraph
44+
let node = newNode i
45+
putGraph $ Map.insert i (toAny node) graph
46+
return node
47+
48+
49+
createInter :: Logged -> ChainDef Inter
50+
createInter l = createNode (\i -> Inter (NodeInfo i l) [])
51+
52+
createSink :: (Distribution d) => Logged -> d -> ChainDef Sink
53+
createSink l d = createNode (\i -> Sink (NodeInfo i l) (MkDistr d))
54+
55+
createSource :: Logged -> ChainDef Source
56+
createSource l = createNode (\i -> Source (NodeInfo i l) [])
57+

Distribution.hs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{-# LANGUAGE GADTs, StandaloneDeriving #-}
2+
3+
module Distribution where
4+
5+
class (Show d) => Distribution d where
6+
-- | give a value provided an x with uniform(0,1) distr
7+
poke :: d -> Double -> Double
8+
9+
10+
data UniDistr = UniDistr
11+
deriving (Show)
12+
13+
instance Distribution UniDistr where
14+
poke UniDistr = id
15+
16+
data ExpDistr = ExpDistr { lambda :: Double }
17+
deriving (Show)
18+
19+
instance Distribution ExpDistr where
20+
poke d x = let l = lambda d in (log (1 - x)) / (-l)
21+
22+
data Distr where
23+
MkDistr :: (Show d, Distribution d) => d -> Distr
24+
deriving instance Show Distr
25+

EventResult.hs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module EventResult where
2+
3+
import Node
4+
5+
data EventResult = EventResult { eventFrom :: NodeId
6+
, eventTo :: NodeId
7+
, timeFrom :: Double
8+
, timeTo :: Double }
9+
deriving (Show)

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
all:
2+
ghc --make Sim.hs && ghc --make CWSim.hs -o cwsim

Node.hs

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{-# LANGUAGE GADTs, StandaloneDeriving #-}
2+
module Node where
3+
4+
import Distribution
5+
6+
import Control.Monad.IO.Class
7+
8+
-- | "flag" passed from user
9+
data Logged = Logged { logName :: String }
10+
| Unlogged
11+
deriving (Show)
12+
class (Show n, NodeClass n) => SrcNode n where
13+
addTrans :: Transition -> n -> n
14+
class (Show n, NodeClass n) => DstNode n where
15+
16+
type NodeId = Integer
17+
18+
type Transition = (DestNode, Distr)
19+
20+
data NodeInfo = NodeInfo { nodeId :: NodeId
21+
, nodeLogged :: Logged }
22+
deriving (Show)
23+
24+
data Source = Source NodeInfo [Transition]
25+
deriving (Show)
26+
instance SrcNode Source where
27+
addTrans t (Source inf ts) = Source inf (t : ts)
28+
29+
data Sink = Sink NodeInfo Distr
30+
deriving (Show)
31+
instance DstNode Sink where
32+
33+
data Inter = Inter NodeInfo [Transition]
34+
deriving (Show)
35+
instance SrcNode Inter where
36+
addTrans t (Inter inf ts) = Inter inf (t : ts)
37+
instance DstNode Inter where
38+
39+
data AnyNode = AnyInter Inter
40+
| AnySource Source
41+
| AnySink Sink
42+
deriving (Show)
43+
44+
foldAny :: (Inter -> a) -> (Source -> a) -> (Sink -> a) -> AnyNode -> a
45+
foldAny a b c d = case d of
46+
AnyInter x -> a x
47+
AnySource x -> b x
48+
AnySink x -> c x
49+
50+
data SourceNode where
51+
MkSourceNode :: (NodeClass n, SrcNode n) => n -> SourceNode
52+
deriving instance Show SourceNode
53+
54+
instance SrcNode SourceNode where
55+
addTrans t (MkSourceNode n) = MkSourceNode (addTrans t n)
56+
57+
data DestNode where
58+
MkDestNode :: (NodeClass n, DstNode n) => n -> DestNode
59+
deriving instance Show DestNode
60+
61+
62+
class (Show n) => NodeClass n where
63+
nodeInfo :: n -> NodeInfo
64+
transitions :: n -> [Transition]
65+
toAny :: n -> AnyNode
66+
67+
instance NodeClass Sink where
68+
nodeInfo (Sink n _) = n
69+
transitions _ = []
70+
toAny = AnySink
71+
72+
instance NodeClass Source where
73+
nodeInfo (Source n _) = n
74+
transitions (Source _ ts) = ts
75+
toAny = AnySource
76+
77+
instance NodeClass Inter where
78+
nodeInfo (Inter n _) = n
79+
transitions (Inter _ ts) = ts
80+
toAny = AnyInter
81+
82+
instance NodeClass AnyNode where
83+
nodeInfo a = foldAny nodeInfo nodeInfo nodeInfo a
84+
transitions a = foldAny transitions transitions transitions a
85+
toAny = id
86+
87+
instance NodeClass DestNode where
88+
nodeInfo (MkDestNode n) = nodeInfo n
89+
transitions (MkDestNode n) = transitions n
90+
toAny (MkDestNode n) = toAny n
91+
92+
instance NodeClass SourceNode where
93+
nodeInfo (MkSourceNode n) = nodeInfo n
94+
transitions (MkSourceNode n) = transitions n
95+
toAny (MkSourceNode n) = toAny n

Random.hs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleInstances #-}
2+
module Random ( RandomT, MonadRandom
3+
, nextRandom
4+
, runRandomT
5+
, runRandomTStd) where
6+
7+
import Control.Monad.State
8+
import Control.Monad.Reader
9+
import Control.Monad.Trans
10+
import Control.Monad.Cont
11+
12+
import qualified System.Random as R
13+
14+
newtype RandomT m a = Random { unRandom :: StateT R.StdGen m a }
15+
deriving (Monad, MonadTrans, MonadState R.StdGen, MonadIO)
16+
17+
class Monad m => MonadRandom m where
18+
nextRandom :: R.Random a => m a
19+
20+
instance Monad m => MonadRandom (RandomT m) where
21+
nextRandom = do
22+
g <- get
23+
let (r, newG) = R.random g
24+
put newG
25+
return r
26+
27+
instance (MonadRandom m) => MonadRandom (StateT s m) where
28+
nextRandom = lift nextRandom
29+
30+
instance (MonadRandom m) => MonadRandom (ReaderT r m) where
31+
nextRandom = lift nextRandom
32+
33+
instance (MonadRandom m) => MonadRandom (ContT r m) where
34+
nextRandom = lift nextRandom
35+
36+
runRandomT :: Monad m => RandomT m a -> R.StdGen -> m a
37+
runRandomT r gen = liftM fst $ runStateT (unRandom r) gen
38+
39+
runRandomTSeed :: Monad m => RandomT m a -> Int -> m a
40+
runRandomTSeed r seed = liftM fst $ runStateT (unRandom r) (R.mkStdGen seed)
41+
42+
runRandomTStd :: MonadIO m => RandomT m a -> m a
43+
runRandomTStd r = liftM fst (runStateT (unRandom r) =<< liftIO R.getStdGen)
44+
45+
46+

Sim.hs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+
module Sim where
3+
4+
import SimChainDef
5+
import Random
6+
import Distribution
7+
import ChainDef
8+
import Node
9+
import EventResult
10+
import SimNode
11+
12+
import Control.Monad.Reader
13+
import Control.Monad.State
14+
import Control.Monad.Identity
15+
import Control.Monad.IO.Class
16+
import Control.Monad.Cont
17+
import Control.Concurrent
18+
import Control.Concurrent.STM
19+
import Data.Maybe
20+
21+
import qualified System.Random as R
22+
import qualified Data.Heap as Heap
23+
import qualified Data.Map as Map
24+
25+
26+
-- | SimT is a transformer representing a simulation
27+
newtype SimT m a = Sim
28+
{ unSim :: ReaderT (ChainDef ())
29+
(ReaderT (Channel MasterEvent)
30+
(ReaderT [ResultVar] m)) a }
31+
deriving (Monad, MonadIO)
32+
33+
instance MonadTrans SimT where
34+
lift = Sim . lift . lift . lift
35+
36+
askMaster :: MonadIO m => SimT m (Channel MasterEvent)
37+
askMaster = Sim . lift $ ask
38+
39+
askResVars :: MonadIO m => SimT m [ResultVar]
40+
askResVars = Sim . lift . lift $ ask
41+
42+
tellMaster :: Channel MasterEvent -> Double -> MasterEvent -> IO ()
43+
tellMaster master time event = atomically $ writeTChan master (time, event)
44+
45+
runSimT :: MonadIO m => SimT m a -> ChainDef () -> m a
46+
runSimT simulation chainDef = do
47+
(masterChannel, resultVars, initGraph) <- liftIO $ initialiseSimGraph chainDef
48+
let graph = wireUpIncomingSimGraph initGraph
49+
let ((), simpleGraph) = runChainDef chainDef
50+
let rng = R.getStdGen
51+
liftIO $ startThreads graph simpleGraph rng
52+
ret <- flip runReaderT resultVars
53+
. flip runReaderT masterChannel
54+
. flip runReaderT chainDef
55+
$ unSim simulation
56+
liftIO $ tellMaster masterChannel 0 EventShutdown
57+
return ret
58+
59+
startThreads :: SimGraph -> Graph -> IO R.StdGen -> IO R.StdGen
60+
startThreads graph simpleGraph rng =
61+
(\f -> Map.foldWithKey f rng graph) $
62+
\nid initInfo lastGen -> do
63+
gen <- lastGen
64+
anyNode <- return $
65+
fromJust (Map.lookup nid simpleGraph)
66+
let (aGen, bGen) = R.split gen
67+
let f a = forkIO (runRandomT (runNode a initInfo) aGen)
68+
foldAny f f f anyNode
69+
return bGen
70+
71+
flushAt :: MonadIO m => Double -> SimT m [(NodeId, [EventResult])]
72+
flushAt time = do
73+
master <- askMaster
74+
liftIO $ tellMaster master time EventFlush
75+
resVars <- askResVars
76+
liftIO . flip mapM resVars $ \(nid, tVar) -> atomically $ do
77+
res <- readTVar tVar
78+
case res of
79+
Nothing -> retry
80+
Just results -> return (nid, results)

0 commit comments

Comments
 (0)