(require (planet "simulation-with-graphics.ss" ("williams" "simulation.plt" 2 1))) (require (planet "random-distributions.ss" ("williams" "science.plt"))) ;;; Simulation parameters (define mode 'open-loop) (define n-attendants 2) (define customer-interarrival-time 4.0) (define attendant-minimum-service-time 2.0) (define attendant-maximum-service-time 10.0) ;;; Simulation model (define attendant #f) (define (generator n) (do ((i 0 (+ i 1))) ((= i n) (void)) (wait (random-exponential customer-interarrival-time)) (schedule now (customer i)))) (define-process (customer i) (with-resource (attendant) (wait/work (random-flat attendant-minimum-service-time attendant-maximum-service-time)))) (define (run-simulation n-runs n-customers-per-run) (with-new-simulation-environment ;; Initialize graphics (begin-busy-cursor) (send run-button enable #f) (send gauge set-range n-runs) (send gauge set-value 0) ;; Execute simulation model (let ((k (make-variable 0))) ; Used for progress gauge (monitor after (set-variable-value! k v) (send gauge set-value v)) (case mode ((open-loop) ;; Open loop processing (let ((max-attendants (make-variable))) (tally (variable-statistics max-attendants)) (tally (variable-history max-attendants)) (do ((i 0 (+ i 1))) ((= i n-runs) (void)) (with-new-simulation-environment (set! attendant (make-resource +inf.0)) (schedule (at 0.0) (generator n-customers-per-run)) (start-simulation) (set-variable-value! max-attendants (variable-maximum (resource-satisfied-variable-n attendant))) (send text erase) (send text insert (format "Open loop processing~n")) (send text insert (format "Number of runs = ~a~n" (variable-n max-attendants))) (send text insert (format "Minimum maximum attendants = ~a~n" (variable-minimum max-attendants))) (send text insert (format "Maximum maximum attendants = ~a~n" (variable-maximum max-attendants))) (set-variable-value! k i))) (send text insert (format "Mean maximum attendants = ~a~n" (variable-mean max-attendants))) (send text insert (format "Variance maximum attendants = ~a~n" (variable-variance max-attendants))) (send text insert (history-plot (variable-history max-attendants) "Maximum Attendants")))) ((closed-loop) ;; Closed loop processing (let ((avg-queue-length (make-variable))) (tally (variable-statistics avg-queue-length)) (tally (variable-history avg-queue-length)) (do ((i 0 (+ i 1))) ((= i n-runs) (void)) (with-new-simulation-environment (set! attendant (make-resource n-attendants)) (schedule (at 0.0) (generator n-customers-per-run)) (start-simulation) (set-variable-value! avg-queue-length (variable-mean (resource-queue-variable-n attendant))) (send text erase) (send text insert (format "Closed loop processing~n")) (send text insert (format "Number of runs = ~a~n" (variable-n avg-queue-length))) (send text insert (format "Minimum average queue length = ~a~n" (variable-minimum avg-queue-length))) (send text insert (format "Maximum average queue length = ~a~n" (variable-maximum avg-queue-length))) (set-variable-value! k i))) (send text insert (format "Mean average queue length = ~a~n" (variable-mean avg-queue-length))) (send text insert (format "Variance average queue length = ~a~n" (variable-variance avg-queue-length))) (send text insert (history-plot (variable-history avg-queue-length) "Average Queue Length"))))) (send run-button enable #t) (end-busy-cursor)))) ;; Simulation graphics (define frame (instantiate frame% ("Open Loop/Closed Loop Analysis"))) (define menu-bar (instantiate menu-bar% (frame))) (define file-menu (instantiate menu% ("&File" menu-bar))) (define exit-menu-item (instantiate menu-item% ("E&xit" file-menu) (callback (lambda (mi e) (exit))))) (define edit-menu (instantiate menu% ("&Edit" menu-bar))) (define options-menu-item (instantiate menu-item% ("Options..." edit-menu) (callback (lambda (mi e) (case mode ((open-loop) (send radio-box set-selection 0) (send slider-3 enable #f)) ((closed-loop) (send radio-box set-selection 1) (send slider-3 enable #t))) (send slider-3 set-value n-attendants) (send text-field-1 set-value (format "~a" customer-interarrival-time)) (send text-field-2 set-value (format "~a" attendant-minimum-service-time)) (send text-field-3 set-value (format "~a" attendant-maximum-service-time)) (send dialog show #t))))) (define panel-1 (instantiate horizontal-panel% (frame) (alignment '(right center)))) (define run-button (instantiate button% ("&Run" panel-1) (horiz-margin 4) (callback (lambda (b e) (run-simulation (send slider-1 get-value) (send slider-2 get-value)))))) (define panel-2 (instantiate vertical-panel% (frame) (style '(border)))) (define slider-1 (instantiate slider% ("Number of runs" 1 1000 panel-2) (init-value 100) (style '(horizontal vertical-label)))) (define slider-2 (instantiate slider% ("Number of customers per run" 1 1000 panel-2) (init-value 500) (style '(horizontal vertical-label)))) (define canvas (instantiate editor-canvas% (frame) (min-width 500) (min-height 400) (style '(no-hscroll no-vscroll)))) (define text (instantiate text% ())) (send canvas set-editor text) (define gauge (instantiate gauge% ("Progress" 1 frame))) (define dialog (instantiate dialog% ("Options" frame))) (define group-box-panel-1 (instantiate group-box-panel% ("Mode" dialog) (alignment '(left top)))) (define radio-box (instantiate radio-box% (#f '("Open loop" "Closed loop") group-box-panel-1) (style '(vertical vertical-label)) (callback (lambda (rb e) (case (send rb get-selection) ((0) (send slider-3 enable #f)) ((1) (send slider-3 enable #t))))))) (define slider-3 (instantiate slider% ("Number of attendants" 1 100 dialog) (init-value 2) (style '(horizontal vertical-label)))) (define group-box-panel-2 (instantiate group-box-panel% ("Customer" dialog))) (define text-field-1 (instantiate text-field% ("Interarrival time" group-box-panel-2))) (define group-box-panel-3 (instantiate group-box-panel% ("Attendant" dialog))) (define text-field-2 (instantiate text-field% ("Minimum service time" group-box-panel-3))) (define text-field-3 (instantiate text-field% ("Maximum service time" group-box-panel-3))) (define panel-3 (instantiate horizontal-panel% (dialog) (alignment '(center center)))) (define cancel-button (instantiate button% ("Cancel" panel-3) (callback (lambda (b e) (send dialog show #f))))) (define ok-button (instantiate button% ("Ok" panel-3) (callback (lambda (b e) (case (send radio-box get-selection) ((0) (set! mode 'open-loop)) ((1) (set! mode 'closed-loop) (set! n-attendants (send slider-3 get-value)))) (set! customer-interarrival-time (string->number (send text-field-1 get-value))) (set! attendant-minimum-service-time (string->number (send text-field-2 get-value))) (set! attendant-maximum-service-time (string->number (send text-field-3 get-value))) (send dialog show #f))))) (send frame show #t)