#lang scheme/base
(require (planet williams/simulation/simulation-with-graphics))
(require (planet williams/science/random-distributions))
(define n 3)
(define m #(1.0 2.0 1.0))
(define p (vector
(make-discrete #(0.0 0.5 0.5 0.0))
(make-discrete #(0.0 0.0 0.8 0.2))
(make-discrete #(0.2 0.0 0.0 0.8))))
(define np '(1 1 1))
(define mu (/ 1.0 1.5))
(define max-messages 10000)
(define n-arrivals 0)
(define n-in-system #f)
(define time-in-system #f)
(define processor #f)
(define-process (message i)
(let ((arrive-time (current-simulation-time))
(work-duration 0.0))
(set-variable-value!
n-in-system (+ (variable-value n-in-system) 1))
(let loop ((node 0)) (when (< node n)
(with-resource ((vector-ref processor node))
(work (random-exponential (vector-ref m node))))
(loop (random-discrete (vector-ref p node)))))
(set-variable-value!
n-in-system (- (variable-value n-in-system) 1))
(set-variable-value!
time-in-system (- (current-simulation-time)
arrive-time))))
(define (generator)
(do ((i 0 (+ i 1)))
((= i max-messages) (void))
(set! n-arrivals (+ n-arrivals 1))
(schedule now (message i))
(wait (random-exponential (/ mu)))))
(define (main)
(with-new-simulation-environment
(set! n-arrivals 0)
(set! n-in-system (make-variable 0))
(accumulate (variable-history n-in-system))
(set! time-in-system (make-variable))
(tally (variable-statistics time-in-system))
(set! processor (list->vector
(map make-resource np)))
(schedule (at 0.0) (generator))
(schedule (at 5000.0) (stop-simulation))
(start-simulation)
(printf "Mean number in system = ~a~n" (variable-mean n-in-system))
(printf "Mean delay in system = ~a~n" (variable-mean time-in-system))
(printf "Total time run = ~a~n" (current-simulation-time))
(printf "Total jobs arrived = ~a~n" n-arrivals)
(printf "Total jobs completed = ~a~n" (variable-n time-in-system))
(printf "Average arrival rate = ~a~n" (/ n-arrivals
(current-simulation-time)))
(write-special (history-plot (variable-history n-in-system)))
(newline)))
(main)