examples/cellphone.ss
#lang scheme/base
;;; Cellphone simulation from PySim

(require (planet williams/simulation/simulation))
(require (planet williams/science/random-distributions))

;;; Parameters

(define Nchannels 4)
(define maxN 1000)
(define lam 1.0)
(define mu 0.6667)
(define meanLifeTime (/ 1.0 mu))
(define Nhours 10)
(define interv 60.0)
(define gap 15.0)

;;; Globals

(define Nfree Nchannels)
(define totalBusyVisits 0)
(define totalBusyTime 0.0)
(define busyStartTime 0.0)
(define busyEndTime 0.0)


;;; Statistics

(define m #f)
(define bn #f)

(define-process (generator n)
  (do ((i 0 (+ i 1)))
      ((= i n) (void))
    (schedule now (job i))
    (wait (random-exponential (/ 1.0 lam)))))

(define-process (job i)
  (when (> Nfree 0)
    (set! Nfree (- Nfree 1))
    (when (= Nfree 0)
      ;; Start busy period
      (set! busyStartTime (current-simulation-time))
      (set! totalBusyVisits (+ totalBusyVisits 1)))
    (work (random-exponential (/ 1.0 mu)))
    (when (= Nfree 0)
      ;; End busy period
      (set! busyEndTime (current-simulation-time))
      (set! totalBusyTime (+ totalBusyTime
                             (- (current-simulation-time)
                                busyStartTime))))
    (set! Nfree (+ Nfree 1))))

(define-process (statistician)
  (do ((i 0 (+ i 1)))
      ((= i Nhours) (void))
    ;; wait the specified gap time
    (wait gap)
    ;; initialize
    (set! totalBusyTime 0.0)
    (set! totalBusyVisits 0)
    (when (= Nfree 0)
      (set! busyStartTime (current-simulation-time)))
    ;; wait the specified interval time
    (wait interv)
    ;; trace busy time and busy visits
    (when (= Nfree 0)
      (set! totalBusyTime (+ totalBusyTime
                             (- (current-simulation-time)
                                busyStartTime))))
    (printf "~a: busy time = ~a; busy visits = ~a~n"
            (current-simulation-time) totalBusyTime totalBusyVisits)
    ;; Tally statistics
    (set-variable-value! m totalBusyTime)
    (set-variable-value! bn totalBusyVisits))
  ;; Print final statistics
  (printf "Busy time:   mean = ~a, variance = ~a~n"
          (variable-mean m) (variable-variance m))
  (printf "Busy number: mean = ~a, variance = ~a~n"
          (variable-mean bn) (variable-variance bn)))

(define (run-simulation)
  (with-new-simulation-environment
   ;; Print parameters
   (printf "lambda = ~a~n" lam)
   (printf "mu     = ~a~n" mu)
   (printf "s      = ~a~n" Nchannels)
   (printf "Nhours = ~a~n" Nhours)
   (printf "interv = ~a~n" interv)
   (printf "gap    = ~a~n" gap)
   ;; Initialize global variables
   (set! Nfree Nchannels)
   (set! totalBusyVisits 0)
   (set! totalBusyTime 0.0)
   (set! busyEndTime 0.0)
   ;; Create statistics
   (set! m (make-variable))
   (tally (variable-statistics m))
   (set! bn (make-variable))
   (tally (variable-statistics bn))
   ;; Create initial processes and start the execution
   (schedule (at 0.0) (generator maxN))
   (schedule (at 0.0) (statistician))
   (schedule (at 10000.0) (stop-simulation))
   (start-simulation)))

(run-simulation)