MagdalenaOlewinska-GroceryStoreLines-EECS- 372
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
Grocery Store Lines Model
The purpose of the Grocery Store Lines model is to describe the impact business decisions have regarding the customer checkout process. This model explores the parameter space from a business’s perspective for both optimizing customer satisfaction through minimum wait times and maximizing customers serviced and optimizing operation costs through minimum operating checkout stations. Queueing theory concepts are applied to produce results that explain phenomena experienced at grocery store checkout lines as well as other applications utilizing multi-server queues.
HOW IT WORKS
Customers enter the store with a random amount of grocery items. They select to enter the checkout line with the shortest line and with the closest distance to the customer. The customer waits in line until it is their turn to be serviced. The checkout station scans the items at a set rate until all items are done at which point the customer leaves the store.
At every minute, customers accumulate wait time as they stand in line and the store accumulates operation costs for each of the checkout stations opened. Their perceived wait time depends on how much time they have spent waiting and how distracted are during this time.
One variation of the model is deciding if the checkout station will be static (the amount of stations opened remains the same for the whole duration of the model) or dynamic (the amount of stations opened changes if more need to be opened because lines are currently too long at that type of station or closed if lines are too short.
Another variation of the model is deciding whether to allow your customers to act impatiently. If the average wait time at the store is 20% over the ideal wait time, customers will refuse to enter a line and thus a sale is lost. If a customer's perceived wait time while waiting in line is 20% over the ideal wait time, the customer will leave the line without being service.
HOW TO USE IT
Initial Checkout Station Count
Set SELF-STATION-COUNT to a number 1 - 5 to set up the corresponding amount of self checkout stations (yellow) that 33% of customers consider and cost the EMPLOYEE-HOURLY-RATE per hour regardless of the amount of stations open
Set GENERAL-STATION-COUNT to a number 1 - 15 to set up the corresponding amount of general checkout stations (blue) that all customers consider and costs the 2*EMPLOYEE-HOURLY-RATE every hour per station
Set EXPRESS-STATION-COUNT to a number 1 - 5 to set up the corresponding amount of express checkout stations (green) that customers with <= 15 items consider and costs the EMPLOYEE-HOURLY-RATE every hour per station
Business Parameters
Set CLOSING-TIME to the amount of hours the store will keep its doors open and accept customers; the simulation ends when the last customer at a checkout station is finished being serviced.
Set EMPLOYEE-HOURLY-RATE to the employee pay rate per hour. Operation costs are deduced from this rate.
Set the DYNAMIC-LAYOUT? switch to TRUE to allow the station layout to dynamically change, or to FALSE to keep your original station settings for the whole duration of the simulation
If DYNAMIC-LAYOUT? is set to TRUE,
->Set EVALUATE-EVERY-X-HOURS to the period at which the lengths of lines are assessed to decide if changes to the current layout are necessary
->Set LINE-TOO-SHORT to the line length at which the grocery store will decide to close that station (if possible) recognizing the-SCHEDULE station as not be efficient enough; a red signal will be lit above the station that will close as soon as all customers already in line there are serviced
->Set LINE-TOO-LONG to the line length at which the grocery store will decide to open another station of that type (if possible), recognizing the station as overworked and adding more stations immediately
Customer Parameters
Set DISTRACTED-IN-LINE to a percentage that a customer's wait time will be distracted by in line last minute buys or other entertainment with the remainder contributing to the customer's perceived wait time
Set IDEAL-WAIT-TIME to a time in minutes customers believe is an appropriate waiting time given the specific store
Set the IMPATIENT-CUSTOMERS? switch to TRUE to enable customers to leave the store if upon arrival the average wait time is 20% over the IDEAL-WAIT-TIME (balk) or if their current wait time in line is 20% over the IDEAL-WAIT-TIME (renege).
Input AVG-#-CUSTOMER-ARRIVING to a number > 0 that represents the average number of customers arriving per minute into the store.
Set CUSTOMER-ARRIVAL-SCHEDULE to "poisson" to have customers arrive following a Poisson distribution pattern, "uniform" to have customers arrive at a constant rate, or "oscillating" to have the customers arrive in periods that go from 0 to 2*AVG then back to 0 customers per tick.
Run the Model
Press the SETUP button.
Press the GO-ONCE button to simulate one minute of the simulation
Press the GO button to begin the simulation.
THINGS TO NOTICE
The Model
Squares near the top of the screen represent checkout stations of each of the types and people appearing at the very top row of the screen represent incoming customers who make their way to the closet station with the least amount of customers. Upon arriving customers obtain a wait number and enter the back of the queue so they can be service following a FIFO priority rule. Once they arrive at the checkout station they remain there until all their groceries have been scanned at which point they leave the store and update the model statistics about their experience. While the customers wait in line, their color changes from light to dark violet the longer their perceieved wait time is currently.
Results & Graphs
Compare the average wait time and total cost of each type of station during the duration of the model.
The Open Checkout Stations graph shows the changes in how many and what kind of stations are open over the duration of the model.
The Customer Departures graph describes visually the breakdown of how each customer left the store (either having checkout, left because of balking, left because of reneging) as stacking the percentages to represent the total number of customers who arrived (vertical slices over time).
The %-YIELD Monitor describes the percentage of customers who entered the store, actually waited long enough to be serviced.
The AVG-WAIT-TIME (MIN) Monitor describes the average wait time in minutes of the customers who have waited in-line and were serviced up until this point.
The TOTAL-COST (DOLLARS) Monitor describes the accumulating cost of operating the store at such a layout.
THINGS TO TRY
With a static model, see how the ratios of different types of checkout stations affect the wait times and cost of the model. To provide the fastest wait time, you need more stations opened but that occurs the most cost. Are some layouts inherently more efficient?
With a dynamic model, see how the too short of an evaluation period coupled with short line lengths marking decisions on when a line is too long and too short can cause a model to increase its average time as actions do not fully have a chance to cause a meaningful impact in the system. Try longer evaluation periods coupled with long line lengths marking decisions on when a line is too long and too short will to see how the cost and average wait time can near that of a static model.
With impatient-customers, see how increasing distraction levels will cause more balking in an inefficient layout for a given customer arrival schedule while decreasing distraction levels will cause more reneging as customers will perceive their wait times for what they are. See how increasing the ideal wait time causes a higher yield of successfully serviced customers and how decreasing the expected wait time can cause huge losses for customer yield. In the latter case, take note that the average wait time for the rest of the model decreases signifcantly as the current capacity of the system is lowered.
EXTENDING THE MODEL
In the dynamic variation of this model, when a checkout station is marked as overworked or underworked, the customers at that station stay in that lane and do not react. Try having some customers relocate to that newly opened stations or choose a different station so a given station can close right away.
Currently the model groups together the queuing principles of balking and reneging. Make seperate switches for each of these customer behaviors and compare the different impacts made on the model.
A characteristic of queueing theory that has not been explored yet is called jockeying where customers switch between queues if they think they will get served faster by doing so. To extend the model with this feature, consider having the checkout stations keep track of their own throughput and having the customers revaluate all the lines as possible queues considering this information of statioini throughput. The customers can reevaluate when their wait-time is close to approaching the ideal wait time or if they notice someone who has arrived after them is being serviced in another line before you.
NETLOGO FEATURES
To create a Poisson distribution which is often used in queueing theory to model an arrival schedule, the following netlogo command was used to report a Poisson-distributed random integer:
random-poisson mean
CREDITS AND REFERENCES
Barrer, D. Y. "Queuing with Impatient Customers and Indifferent Clerks." Operations Research 5.5 (1957): 644-49. Print.
Blackburn, Joseph D. "Optimal Control of a Single-Server Queue with Balking and Reneging." Management Science 19.3 (1972): 297-313. Print.
Wilensky, U. (1999). NetLogo [computer software]. Evanston, IL: Center for Connected Learning and Computer-Based Modeling, Northwestern University. http://ccl.northwestern.edu/netlogo .
Comments and Questions
globals [ ;;NOTE: SAVED INPUT, so if user changes parameters after pressing setup, model characteristics will not change thus running model will still be correct ;; model characteristics stations ;; patches that are designated stations ;; business characteristics closing-at ;; tick count at which no more customers should arrive hourly-pay ;; employee hourly rate dynamic? ;; true if stations can dynamically open & close dynamic-check-range ;; evaluate whether to open/close stations every X hours (increments in half hour units) short-line-length ;; close a station (if possible) if a station's line is shorter than this number @half hour marks long-line-length ;; open a new station (if possible) if a station's line is longer than this number @half hour marks ;; customer characteristics distraction-level ;; decreases a customer's sense of wait-time by % of distraction provided impatience? ;; allows unsatisfied customers to balk if average wait of store is large or renege when perceived wait while in line too large ideal-wait ;; time (in min) believed to be best waiting time at this particular grocery store avg-arrival-count ;; average number of customers arriving per tick arrival-schedule ;; schedule of customer arrival with average as avg-arrival-count: uniform, oscillating ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; running totals all-total-wait ;; running total of all wait time of all customers since store opening total-customers ;; running total of all arrivals total-checkout-customers ;; running total of all customers who successfully checked out total-balk-customers ;; running total of all customers who arrived but left because avg. wait time too long total-renege-customers ;; running total of all customers who waited but left because his/her wait time too long in line general-total-wait ;; running total of all wait time of customers serviced at a general checkout station since store opening general-total-customers ;; running total of all customers serviced at a general checkout station since store opening express-total-wait ;; running total of all wait time of customers serviced at an express checkout station since store opening express-total-customers ;; running total of all customers serviced at an express checkout station since store opening self-total-wait ;; running total of all wait time of customers serviced at a self-checkout station since store opening self-total-customers ;; running total of all customers serviced at a self-checkout station since store opening ;; report to user statistics average-wait ;; tracks average total time waited of a customer now "checking-out" and leaving general-average-wait ;; average-wait but for general stations express-average-wait ;; average-wait but for express stations self-average-wait ;; average-wait but for self stations current-cost ;; tracks cost of operation depending on how many and what types of checkout stations are open total-general ;; current cost of general stations total-express ;; current cost of express stations total-self ;; current cost of self checkout stations ] breed [customers customer] patches-own [ max-items ;; depending on type of station, how many max scan-rate ;; how many items per tick stations scans line-length ;; keeps track of line length; 0 if no one is in line interested-customers ;; keeps track of count of customers who have selected this line (location = here , state "found-line" or "in-line") total-items-scanned ;; keeps track of number of items scanned total-customers-helped ;; keeps track how many customers serviced last-number-served ;; keeps track ensures next customer being served has larger wait-number about-to-close? ;; if true, inefficient so will close as soon as customers in line serviced, no new customers accepted #-renege-customers ;; keeps track how many customers left line because wait too long ] customers-own [ state ;; no-line, found-line, in-line, checking-out grocery-items ;; number items needed to be checked out wait-number ;; indicates place in line wait-time ;; counts how long has been "in-line" perceived-wait-time ;; how long the customer perceives he/she is in line dependent on distractions location ;; checkout station the customer has selected ] ;;; setup procedures to setup clear-all set-store-characteristics setup-stations reset-ticks end ;; go procedure to go if ticks > closing-at and count customers = 0 ;;end simulation after all customers leave and it is past closing time [stop] if ticks > 0 and ticks mod dynamic-check-range = 0 and dynamic? [adjust-open-stations] ;;access layout and make changes every evaluation period if impatience? [balk-customers] check-out-customers find-line move-forward if impatience? [renege-customers] leave-customers if dynamic? [close-stations] if ticks < closing-at [arrive-customers] ;;keep doors open to customers for indicated period color-customers update-graphs update-plots tick end ;;; setup helper procedure ;;; set up global variables. this includes using user inputs to initialize store characteristics to set-store-characteristics set closing-at (closing-time * 60) ;convert hours to tick count (1 tick = 1 minute) set dynamic-check-range (evaluate-every-X-hours * 60) set distraction-level distracted-in-line set impatience? impatient-customers? set ideal-wait ideal-wait-time set hourly-pay employee-hourly-rate set dynamic? dynamic-layout? set short-line-length line-too-short set long-line-length line-too-long set arrival-schedule customer-arrival-schedule set avg-arrival-count avg-#-customers-arriving end ;; patch procedure ;; set up checkout stations based on user parameters to setup-stations ;; floor is white ask patches [set pcolor grey + 3 ] ;; create stations of each type let new-station 0 ;;not used for initial creation open-new-station blue general-stations new-station open-new-station green express-stations new-station open-new-station yellow self-stations new-station end ;; patch procedure ;; open new-station-count amount of stations with pcolor checkout-type to open-new-station [checkout-type new-station-count new-station-loc] ;; set up check out area on y axis = 6 let station-space patches with [pycor = 14 and pxcor mod 2 = 0] set station-space station-space with [pcolor = grey + 3] let express-space station-space with [pxcor >= 16] let general-space station-space with [pxcor > -16 and pxcor < 16] let self-space station-space with [pxcor <= -16] if checkout-type = blue [set station-space n-of new-station-count general-space] if checkout-type = green [set station-space min-n-of new-station-count express-space [pxcor]] if checkout-type = yellow [set station-space max-n-of new-station-count self-space [pxcor]] ;;create num-to-open patches of checkout-type (pcolor indicating type) ask station-space [set pcolor checkout-type if-else pcolor = green [set max-items 15] ;;express types have grocery-item count restriction of <= 15 items [set max-items 1000] if-else pcolor = yellow [set scan-rate 10] ;;self-checkout types have slower scan-rates [set scan-rate 15] set line-length 0 set interested-customers 0 set total-items-scanned 0 set total-customers-helped 0 set last-number-served 0 set #-renege-customers 0 set about-to-close? false set new-station-loc self] set stations patches with [pcolor != grey + 3] end ;;customer procedure ;; queueing theory: balking - just arrived customer chooses not to join queue because wait time is too long to balk-customers ask customers with [state = "no-line"] [ ;; leave if model's wait time is 20% higher than ideal wait if impatience? and average-wait > (1.20 * ideal-wait) [set total-balk-customers total-balk-customers + 1 die] ] end ;;customer procedure ;; queueing theory: reneging - leaving queue without being serviced because wait is too long to renege-customers ask customers with [state = "in-line"] [ ;; leave if customer's preceived wait time is 20% higher than ideal wait if perceived-wait-time > (1.20 * ideal-wait) [ask location [;set line-length line-length - 1 set interested-customers interested-customers - 1 set #-renege-customers #-renege-customers + 1 ask customers with [state = "in-line" and location = self] [set wait-number wait-number - 1] ] set total-renege-customers total-renege-customers + 1 die] ] ask stations with [#-renege-customers > 0] [ let reg #-renege-customers ask customers with [location = myself and state = "in-line"] [if reg >= 2 [move-to patch-ahead (reg - 2)]] set #-renege-customers 0 ] end ;; patch procedure ;; at every user indicated dynamic-range-check increment in time, if dynamic-layout? is switched on: ;; evaluate line-length per station (note: stations open cannot exceed max allowed for store: 5 - express, self; 15 - general) ;; if line-length <= close-if-line-shorter-than: mark station to be closed, ;; customers "found-line" heading to this underwhelmed station will have to pick new station ;; current customers "in-line" will still be serviced ;; if line-length >= open-if-line-longer-than: open new station of same type, ;; customers "found-line" heading to this overwhelmed station will be redirected to new station to adjust-open-stations ask patches with [pcolor = green or pcolor = blue or pcolor = yellow] [ let given-color pcolor let my-type-of-stations stations with [pcolor = given-color] if count my-type-of-stations with [about-to-close? = false] > 1 ;;range for any given checkout type is to have between 1-15 stations open at any time [ if line-length <= short-line-length ;; line too short and at least one type of this station open [set about-to-close? true ask patch pxcor (pycor + 1) [set pcolor red]] ] let current-line line-length let max-amount 5 ;; max amount of express or self checkout stations is 5 if pcolor = blue [set max-amount 15] ;; max amount of general stations is 15 if count my-type-of-stations < max-amount [ if line-length >= long-line-length ;; line too long and still room for more stations so open a station like this [let new-station self open-new-station pcolor 1 new-station ask customers with [location = myself and state = "found-line"] ;;relocate customers who chose this line but havent arrived yet to redirect to new open station [set location new-station ask new-station [set about-to-close? false set interested-customers interested-customers + 1] ask location [set interested-customers interested-customers - 1] face location] ] ] set stations patches with [pcolor != grey + 3] ] end ;; patch procedure ;; if dynamic-layout? switched on and marked to close ASAP, ;; actually close when all customers who were already in line serviced to close-stations ask stations with [about-to-close? = true and count customers-here = 0 and interested-customers = 0] [set pcolor grey + 3 ask patch pxcor (pycor + 1) [set pcolor grey + 3] set stations patches with [pcolor != grey + 3]] end ;; customer procedure ;; if you have no more grocery items while checking out, leave the store, ;; decrease the station's line-length, increase the station's customers helped count, ;; and decrease the wait-number of everyone who was in your checkout line to leave-customers ask customers with [state = "checking-out"] [if grocery-items <= 0 [let num wait-number ask location [set line-length line-length - 1 set interested-customers interested-customers - 1 set total-customers-helped total-customers-helped + 1] update-statistics die] ] end ;; customer procedure ;; if checking-out, decrease your grocery-items by the scan-rate of the station ;; and increase the total-items-scanned count of the station by the number of items scanned ;; if in-line, increase your wait time, if you are the smallest wait-number in your patch, ;; move up and set state to checking-out to check-out-customers ask customers with [state = "checking-out"] [ let scan 0 let num wait-number let just-arrived false ask patch-here [set scan scan-rate if last-number-served != num [set just-arrived true set last-number-served num] ] if just-arrived = false ;; every station has 1 minute of transaction overall [ if grocery-items < scan [set scan grocery-items] set grocery-items grocery-items - scan ask patch-here [set total-items-scanned total-items-scanned + scan] ] ] end ;; customer procedure ;; if station is in front of you, ask the station to increase its line-length, assign ;; yourself a customer of the day number as your wait-number, and set your state to in-line ;; if station is not in front of you, keep moving forward toward your selected station to move-forward ask customers with [state = "in-line"] [ set wait-time wait-time + 1 set perceived-wait-time perceived-wait-time + (1 - (distraction-level / 100)) if-else patch-here = location [set state "checking-out" set label-color red set color white] [let customers-ahead 1000 ask patch-ahead 1 [set customers-ahead count customers-here] if customers-ahead = 0 and wait-number = min [wait-number] of customers-here [ if patch-here != location [move-to patch-ahead 1 let temp 0 ask patch-ahead 1 [ask customers-here with [state = "in-line" or state = "checking-out"] with-max [wait-number] [set temp wait-number]] if temp > wait-number and patch-here != location [move-to patch-ahead 1]] if patch-here = location [set state "checking-out" set label-color red set color white]] ;; ask patch-here [if last-number-served >= [wait-number] of myself [type "ERROR: queueing out of order at station: " type pxcor type " " type last-number-served type " > " print [wait-number] of myself]]] ]] ask customers with [state = "found-line"] [ let w 1000 let new-x pxcor let new-y pycor if-else patch-ahead 1 = location [ask location [set line-length line-length + 1 set new-x pxcor set new-y pycor - line-length ; if count customers-here with [state = "checking-out"] > 0 [set new-y new-y + 1] set w total-customers-helped + line-length] set state "in-line" set color grey set wait-number w set heading 0 if-else new-y > -18 [move-to patch new-x new-y] ;; move to end of line [move-to patch new-x -18];; end of line would be off screen, so group together at the last patch ] [fd 1] ] end ;; customers procedure ;; for customers with no-line state, pick the shortest lines closet to you and set ;; state to found-line to find-line ask customers with [state = "no-line"] [ let my-items grocery-items let options 0 if-else random 101 <= 33 [set location stations with [max-items >= my-items and about-to-close? = false] with-min [interested-customers] let selection min-one-of location [distance myself] set location selection ask location [set interested-customers interested-customers + 1] ] [set location stations with [max-items >= my-items and about-to-close? = false and pcolor != yellow] with-min [interested-customers] let selection min-one-of location [distance myself] set location selection ask location [set interested-customers interested-customers + 1] ] set state "found-line" face location ] end ;; customers procedure ;; create customers based on arrival-schedule preference set; ;; uniform creates X amount of customers at every tick (x user input value ;; max store capacity set at 500 to arrive-customers let num-arriving 0 let customer-count floor(avg-arrival-count) if-else customer-count <= 0 [user-message "Error: Number of customers arriving must be greather than zero."] [if arrival-schedule = "uniform" ;; arrive user input # of customers per tick [set num-arriving customer-count] if arrival-schedule = "oscillating" ;; arrive variable customers with max of user input # [set customer-count customer-count * 2 set num-arriving ticks mod (customer-count * 2) + 1 if num-arriving > customer-count ;; past max magnitude of oscillation needs to count backwards [set num-arriving -1 * (num-arriving - (customer-count * 2))] ] if arrival-schedule = "poisson" ;; arrive with poisson distribution of user input # average [set num-arriving random-poisson customer-count] ] create-customers num-arriving [ setxy random 28 - 14 18 ;; enter at the top of screen in the middle set shape "person" set state "no-line" ;; no decision on any line at first set grocery-items 1 + random 99 ;; random amount of items 1 - 100 set wait-number 1000 ;; default head to very back set wait-time 0 ;; start off with no wait time set perceived-wait-time 0 ;; start off with no perceived wait time set size 1 ;set label grocery-items set label-color white ] set total-customers (total-customers + num-arriving) end ;;customer procedure ;; customers go across the violet color spectrum with deeper violets indicating longer ;; perceived-wait-times as compared to the ideal wait to color-customers ask customers with [state = "in-line"] [set color scale-color violet perceived-wait-time (1.20 * ideal-wait) 0] end ;; calculates current-cost, per checkout cost, ;; overall average wait, per checkout type average wait to update-graphs let general-count count stations with [pcolor = blue] let express-count count stations with [pcolor = green] let self-count count stations with [pcolor = yellow] let temp-g general-count * 2 * (hourly-pay / 60) ;; 2 employees for general station (scanner + bagger) let temp-e express-count * (hourly-pay / 60) ;; 1 employee for express station (scanner) let temp-s 0 if self-count > 0 ;; 1 employee oversees all self checkouts [set temp-s (hourly-pay / 60)] set total-general total-general + temp-g set total-express total-express + temp-e set total-self total-self + temp-s set current-cost current-cost + temp-g + temp-e + temp-s if total-checkout-customers > 0 [set average-wait all-total-wait / total-checkout-customers] if general-total-customers > 0 [set general-average-wait general-total-wait / general-total-customers] if express-total-customers > 0 [set express-average-wait express-total-wait / express-total-customers] if self-total-customers > 0 [set self-average-wait self-total-wait / self-total-customers] end ;; after customers check out, ;; update global statistics across all checkout station types to update-statistics set all-total-wait all-total-wait + wait-time set total-checkout-customers total-checkout-customers + 1 let type-checkout "" ask patch-here [if pcolor = blue [set type-checkout "general"] if pcolor = green [set type-checkout "express"] if pcolor = yellow [set type-checkout "self"]] if type-checkout = "general" [set general-total-wait general-total-wait + wait-time set general-total-customers general-total-customers + 1] if type-checkout = "express" [set express-total-wait express-total-wait + wait-time set express-total-customers express-total-customers + 1] if type-checkout = "self" [set self-total-wait self-total-wait + wait-time set self-total-customers self-total-customers + 1] end
There are 4 versions of this model.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
MagdalenaOlewinska-GroceryStoreLines-EECS- 372.png | preview | Preview for 'MagdalenaOlewinska-GroceryStoreLines-EECS- 372' | over 9 years ago, by Magdalena Olewinska | Download |
MagdalenaOlewinska_May16.docx | word | Progress Report 2 | over 9 years ago, by Magdalena Olewinska | Download |
MagdalenaOlewinska_May23.docx | word | Progress Report 3 | over 9 years ago, by Magdalena Olewinska | Download |
MagdalenaOlewinska_May9.docx | word | Progress Report 1 | over 9 years ago, by Magdalena Olewinska | Download |
This model does not have any ancestors.
This model does not have any descendants.