Argyle St Model
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
The Argyle Model attempts to demonstrate how factors of proximity and quality of product affect the success of a business. It is inspired by the Argyle Street in north Chicagoland, where dozens Vietnamese pho restaurants compete for business within a few blocks of each other.
HOW IT WORKS
Each patron has a hunger level that increases with every tick, and they wait at the El Train Station at the left edge of the screen until that level reaches 100. At that point, they begin searching for a restaurant to eat by moving forward and wiggling randomly. Once they find a restaurant, they will eat there, then depending on the taste rating of the restaurant, they might remember it as a favorite. Patrons will also keep track of restaurants they particularly dislike. Next time a patron becomes hungry, it may choose to go straight for its favorite rather than searching.
Each restaurant has a random value of taste and capacity. If the number of patrons eating at the restaurant is equal to its capacity, it will not allow any more to enter. Restaurants will also keep track of how many patrons they attract, in a variable called patronage. At the end of a fiscal period restaurants with a high patronage will be allowed to move one space closer to the El Station.
HOW TO USE IT
Control the initial setup of the environment using the sliders to the left of the display. the number-patrons controls the initial number of patrons, the patron-turnover controls how quickly patrons will die and be hatched, and average-capacity and capacity-variation control the restaurants' capacity. fiscal-period-length controls how often restuarants will get an opportunity to change locations. The two-dimensional? switch and all sliders below it control the geographical setup with streets going in both directions.
On the far left, plots of patronage, distance from the El Station, and taste are all plotted against each other. The correlation coefficients of the three plots are calculated in real time and also displayed. Finally, there are displays of the patron populations and their activities.
THINGS TO NOTICE
The key to understanding the model is observing the behavior of the scatter plots and what kind of trends emerge over time. Notice which trends become well defined first, especially when values like capacity and patron-turnover are changed.
THINGS TO TRY
See what happens to the strength of the calculated correlation coefficients when the patron-turnover rate or average-capacity is adjusted.
EXTENDING THE MODEL
This model may be extended by providing communication networks between patrons. It is rather unrealistic to assume that non of the patrons would share with their friends the news of a particularly delicious restaurant. Adding this feature may yield very different results within the model.
Another feature worth trying would be to add another common entry point for patrons. Doing so would affect how important proximity from the El is to a business' success.
Comments and Questions
breed[patrons patron] breed[vacancy-lights vacancy-light] breed[trains train] patrons-own[t-radius hunger searching eating returning bypassing R0x R0y R1x R1y R1p] ; R0x and R0y are the disliked restaurant coords, R1x and R1y are the liked restaurant coords ; R1p is the loyalty rating (or preference) of the liked restaurant patches-own[capacity taste patronage restaurant? orig-x orig-y] ; orig-x and orig-y refer to the original coordinates of the restaurant globals[rush-countdown fiscal-term-count taste-patronage-corr dist-patronage-corr dist-taste-corr] to setup ifelse two-dimensional? [setup-2D] [setup-1D] end ;;==================================================SETUP 1D MODE================================================================= to setup-1D ;; setup the environment ca set rush-countdown 1000 set fiscal-term-count 1 ask patches[ set pcolor white set orig-x pxcor set orig-y pycor set restaurant? 0 if(pxcor = -7)[set pcolor 17] if((pxcor > -7) and (abs(pycor) = 2))[ ;; setup restaurants 1-D for this first model set restaurant? 1 set pcolor lime set patronage 0 set taste random 100 set capacity (random capacity-variation) + (average-capacity - (capacity-variation / 2)) if(capacity < 1)[set capacity 1] sprout-vacancy-lights 1[ set shape "square" ;; this will act as the restaurant's vacancy light! set color white set size .8 set label-color black ] ] if((pxcor > -7) and (abs(pycor) > 2))[set pcolor brown] if((pxcor = -7) and (abs(pycor) < 2))[set pcolor blue] ;; setup home base for turtles to live between meals if((pxcor = -7) and (pycor = 0))[ sprout-trains 1[ set shape "train passenger car" set color gray + 3 set size 2 set heading 0 ] ] ] create-patrons number-patrons[ initialize-patrons ] end ;==============================================================TO SETUP-2D=========================================================== to setup-2D ;; setup the environment ca set rush-countdown 1000 set fiscal-term-count 5000 set fiscal-term-count 1 ask patches[ set orig-x pxcor set orig-y pycor set pcolor white set restaurant? 0 if(pxcor = -7)[set pcolor 17] if((pxcor = -7) and (pycor = 0))[ sprout-trains 1[ set shape "train passenger car" set color gray + 3 set size 2 set heading 0 ] ] if((pxcor > -6) and ((pxcor mod (7 - N-S-street-density)) != 0) and ((pycor mod (7 - E-W-street-density))!= 0))[ ;; setup restaurants 1-D for this first model ifelse(wide-boulevards?)[ if((abs(pxcor) > 1) and (abs(pycor) > 1))[ ifelse(random 100 < restaurant-density)[ set restaurant? 1 set pcolor lime set patronage 0 set taste random 100 set capacity (random capacity-variation) + (average-capacity - (capacity-variation / 2)) if(capacity < 1)[set capacity 1] ;make sure each restaurant has at least capacity of 1 sprout-vacancy-lights 1[ set shape "square" ;; this will act as the restaurant's vacancy light! set color white set size .8 set label-color black ] ] [ set pcolor brown ] ] ] [ ifelse(random 100 < restaurant-density)[ set restaurant? 1 set pcolor lime set patronage 0 set taste random 100 set capacity (random capacity-variation) + (average-capacity - (capacity-variation / 2)) if(capacity < 1)[set capacity 1] ;make sure each restaurant has at least capacity of 1 sprout-vacancy-lights 1[ set shape "square" ;; this will act as the restaurant's vacancy light! set color white set size .8 set label-color black ] ] [ set pcolor brown ] ] ] if((pxcor = -7) and (abs(pycor) < 2))[set pcolor blue] ;; setup home base for turtles to live between meals ] ask patches with [restaurant? = 1][ if ((count neighbors4 with [pcolor = white]) = 0)[ ;; if they have no street access, don't make them a restaurant set pcolor brown set restaurant? 0 ask turtles-here[die] ] ] create-patrons number-patrons[ initialize-patrons ] end ;==============================================================TO GO================================================================== to go check-rush check-fiscal ask patrons[ check-bypass check-eating check-hunger check-returning check-searching if(random 100000 < patron-turnover) [die] ] ask vacancy-lights[ check-capacity ] ask patches[ update-patronage ] ask vacancy-lights[ set label [patronage] of patch-here ] ask trains[ move ] update-charts end ;==================================================================================================================================== to check-location ;; check if this is somewhere the turtle wants to eat if([restaurant?] of patch-here = 1)[ ifelse(random 200 < hunger) ;; the hungrier the turtle is, the more likely it is to enter a restaurant [enter-restaurant] ;; if the turtles are on a restaurant and like it, they will stop searching. Otherwise, turn around [keep-searching] ] if([pcolor] of patch-here = brown)[keep-searching] end to check-eating if(eating = 1)[ set searching 0 set hunger (hunger - 5) ;; while eating, the turtle becomes less hungry if(hunger <= 0)[ set eating 0 ;; no longer hungry set returning 1 ] ;; when the turtle is no longer hungry, it will return home ] end to check-hunger if((hunger > 100) and ([pcolor] of patch-here = blue))[ ifelse((random 200 < R1p ) and (R1y != 0)) ;; choose if the turtle is going to search, or go straight to it's favorite restaurant [set bypassing 1] [set searching 1] ] set hunger (hunger + 1) ;; every tick the turtle gets more hungry end to check-returning if(returning = 1)[ facexy -7 0 fd .2 if([pcolor] of patch-here = blue)[set returning 0] ] end to check-searching if(searching = 1)[ set heading (heading + (random t-radius) - (random t-radius)) ;; have the turtles wiggle, then move forward if(xcor < -6)[set heading 90] ;; if turtle is out of bounds, send them in the right direction fd .1 check-location ] end to check-bypass if(bypassing = 1)[ let t-R1x R1x let t-R1y R1y let x-go [pxcor] of (patches with [(orig-x = t-R1x) and (orig-y = t-R1y)]) ;; go to the favorite restaurant, even if it has changed location let y-go [pycor] of (patches with [(orig-x = t-R1x) and (orig-y = t-R1y)]) facexy (one-of x-go) (one-of y-go) fd .1 if(([orig-x] of patch-here = R1x) and ([orig-y] of patch-here = R1y))[enter-restaurant] ] end to enter-restaurant if(([orig-x] of patch-here = R0x) and ([orig-y] of patch-here = R0y))[ keep-searching];; if this is a restaurant the turtle dislikes, keep searching ifelse((count patrons-here) > ([capacity] of patch-here)) ;; make sure the restaurant hasn't reached capacity. If it has, we continue searching [ keep-searching ] [ set bypassing 0 ;; no longer in bypass mode set searching 0 ;; no longer in search mode set eating 1 ;; we found the restaurant, we're happy! ask patch-here[ set patronage patronage + 1 if(pcolor > 60)[ set pcolor (pcolor - 1) ;; readjust patch color if(pcolor < 60)[set pcolor 60] ;; make sure readjustment doesn't overshoot ] ] ;; have the restaurant remember that they had another customer ] ifelse((R1x = [orig-x] of patch-here) and (R1y = [orig-y] of patch-here)) [ set R1p (R1p + 20) if(R1p > 190)[set R1p 190] ;; make sure the preference factor doesn't go over 90 ] [if((random 100 < ([taste] of patch-here)) and ([taste] of patch-here >= 60))[ set R1x ([orig-x] of patch-here) ;; have the turtle remember this restaurant if they liked it set R1y ([orig-y] of patch-here) set R1p ([taste] of patch-here) ] ] if(([taste] of patch-here) < 30)[ set R0x ([orig-x] of patch-here) ;; have the turtle remember this restaurant if they disliked it set R0y ([orig-y] of patch-here) ] end to check-capacity ifelse((count patrons-here) >= [capacity] of patch-here) [set color red] ;; if a restaurant's capacity has been reached, signal by turning red [set color white] end to keep-searching set searching 1 set bypassing 0 set heading (heading + 180 + random 80 - random 80) fd .5 end to check-rush if(rush-countdown = 75)[ ask patrons[ if(random 2 < 1)[ set hunger 0 set searching 0 set bypassing 0 set returning 1 ] ] ] if(rush-countdown = 0)[ ask patrons[if([pcolor] of patch-here = blue)[set hunger 100]] ;;have each turtle release every 1000 ticks set rush-countdown 1000 create-patrons (.01 * patron-turnover * number-patrons)[ initialize-patrons ] ] set rush-countdown (rush-countdown - 1) end to update-patronage ;; have the restaurants display their normalized patronage if((restaurant? = 1) and (pcolor < 69))[set pcolor (pcolor + .01)] end to update-charts ;; let's plot some stuff! set-current-plot "Distance vs. Taste" clear-plot set-plot-pen-mode 2 ask patches with [restaurant? = 1][ let my-x-dist (distancexy -7 pycor) let my-y-dist (distancexy pxcor 0) plotxy (my-x-dist + my-y-dist) taste ] set-current-plot "Patronage Distribution" set-histogram-num-bars 10 set-plot-pen-mode 1 histogram ([70 - pcolor] of (patches with [restaurant? = 1])) tick set-current-plot "Taste vs. Patronage" clear-plot set-plot-pen-mode 2 ask patches with [restaurant? = 1][ plotxy taste (100 * patronage / fiscal-term-count) ] set-current-plot "Distance vs. Patronage" clear-plot set-plot-pen-mode 2 ask patches with [restaurant? = 1][ let my-x-dist (distancexy -7 pycor) let my-y-dist (distancexy pxcor 0) plotxy (my-x-dist + my-y-dist) (100 * patronage / fiscal-term-count) ] let tlist sum [taste] of patches with [restaurant? = 1] ;; calculate some correlation coefficients! let plist sum [patronage] of patches with [restaurant? = 1] let dlist sum [distance patch -7 0] of patches with [restaurant? = 1] let N count patches with [restaurant? = 1] let tlist2 sum [taste ^ 2] of patches with [restaurant? = 1] let plist2 sum [patronage ^ 2] of patches with [restaurant? = 1] let dlist2 sum [(distance patch -7 0) ^ 2] of patches with [restaurant? = 1] let tplist sum [taste * patronage] of patches with [restaurant? = 1] let tdlist sum [taste * (distance patch -7 0)] of patches with [restaurant? = 1] let dplist sum [(distance patch -7 0) * patronage] of patches with [restaurant? = 1] if((N * (tlist2 - 1)) * (N * (plist2 - 1)) > 0)[ set taste-patronage-corr ( ((N * tplist) - (tlist * plist)) / sqrt((N * (tlist2 - 1)) * (N * (plist2 - 1)))) ] if((N * (dlist2 - 1)) * (N * (plist2 - 1)) > 0)[ set dist-patronage-corr ( ((N * dplist) - (dlist * plist)) / sqrt((N * (dlist2 - 1)) * (N * (plist2 - 1)))) ] if((N * (dlist2 - 1)) * (N * (tlist2 - 1)) > 0)[ set dist-taste-corr ( ((N * tdlist) - (dlist * tlist)) / sqrt( (N * (dlist2 - 1)) * (N * (tlist2 - 1)) )) ] end to move fd .015 if(ycor > 7.499999)[ set ycor -7.5] end to initialize-patrons setxy -7 0 ;; have the turtles start out at their home base ifelse(pirate-mode?)[ set shape "pirate" set size ((random 4) + 1) / 2 ] [set shape "person"] set heading 90 set hunger random 100 set R0x 0 set R0y 0 set R1x 0 set R1y 0 set t-radius 20 + random 30 end to check-fiscal set fiscal-term-count (fiscal-term-count + 1) if (fiscal-term-count = fiscal-period-length)[ set fiscal-term-count 1 ask patches[ ; switch restaurants if(patches-move?)[ ifelse(abs(pycor) != max-pycor)[ if((([pcolor] of patch pxcor (pycor + 1)) = white) or (([pcolor] of patch pxcor (pycor - 1)) = white)) [move-left] ] [ ifelse(pycor > 0) [if(([pcolor] of patch pxcor (pycor - 1)) = white)[move-left]] [if(([pcolor] of patch pxcor (pycor + 1)) = white)[move-left]] ] ifelse(abs(pxcor) != max-pxcor)[ if((([pcolor] of patch (pxcor + 1) pycor) = white) or (([pcolor] of patch (pxcor - 1) pycor) = white))[ ifelse(pycor > 0) [move-down] [move-up] ] ] [ ifelse(pycor > 0) [if((([pcolor] of patch pxcor (pycor - 1)) = white))[move-down]] [if((([pcolor] of patch pxcor (pycor + 1)) = white))[move-up]] ] ] set patronage 0 ] ask patches[ if(pcolor = brown)[ ask vacancy-lights-here[die]] ;; if no longer a restaurant, have the light die ] ] end to move-left if((patch (pxcor - 1) pycor != nobody) and ([pcolor] of patch (pxcor - 1) pycor != white) and (pxcor > -6))[ if(([patronage] of patch (pxcor - 1) pycor) < patronage - (fiscal-period-length / 100))[ let t-capacity ([capacity] of patch (pxcor - 1) pycor) let t-taste ([taste] of patch (pxcor - 1) pycor) let t-restaurant? ([restaurant?] of patch (pxcor - 1) pycor) let t-orig-x ([orig-x] of patch (pxcor - 1) pycor) let t-orig-y ([orig-y] of patch (pxcor - 1) pycor) let t-pcolor ([pcolor] of patch (pxcor - 1) pycor) ask (patch (pxcor - 1) pycor)[ set capacity ([capacity] of myself) set taste ([taste] of myself) set restaurant? ([restaurant?] of myself) set orig-x ([orig-x] of myself) set orig-y ([orig-y] of myself) set pcolor ([pcolor] of myself) sprout-vacancy-lights 1[ set shape "square" ;; this will act as the restaurant's vacancy light! set color white set size .8 set label-color black ] ] set capacity t-capacity set taste t-taste set restaurant? t-restaurant? set orig-x t-orig-x set orig-y t-orig-y set pcolor t-pcolor ] ] end to move-down if((patch pxcor (pycor - 1) != nobody) and ([pcolor] of patch pxcor (pycor - 1) != white))[ if(([patronage] of patch pxcor (pycor - 1)) < patronage - (fiscal-period-length / 100))[ let t-capacity ([capacity] of patch pxcor (pycor - 1)) let t-taste ([taste] of patch pxcor (pycor - 1)) let t-restaurant? ([restaurant?] of patch pxcor (pycor - 1)) let t-orig-x ([orig-x] of patch pxcor (pycor - 1)) let t-orig-y ([orig-y] of patch pxcor (pycor - 1)) let t-pcolor ([pcolor] of patch pxcor (pycor - 1)) ask(patch pxcor (pycor - 1))[ set capacity ([capacity] of myself) set taste ([taste] of myself) set restaurant? ([restaurant?] of myself) set orig-x ([orig-x] of myself) set orig-y ([orig-y] of myself) set pcolor ([pcolor] of myself) sprout-vacancy-lights 1[ set shape "square" ;; this will act as the restaurant's vacancy light! set color white set size .8 set label-color black ] ] set capacity t-capacity set taste t-taste set restaurant? t-restaurant? set orig-x t-orig-x set orig-y t-orig-y set pcolor t-pcolor ] ] end to move-up if((patch pxcor (pycor + 1) != nobody) and ([pcolor] of patch pxcor (pycor + 1) != white))[ if(([patronage] of patch pxcor (pycor + 1)) < patronage - (fiscal-period-length / 100))[ let t-capacity ([capacity] of patch pxcor (pycor + 1)) let t-taste ([taste] of patch pxcor (pycor + 1)) let t-restaurant? ([restaurant?] of patch pxcor (pycor + 1)) let t-orig-x ([orig-x] of patch pxcor (pycor + 1)) let t-orig-y ([orig-y] of patch pxcor (pycor + 1)) let t-pcolor ([pcolor] of patch pxcor (pycor + 1)) ask(patch pxcor (pycor + 1))[ set capacity ([capacity] of myself) set taste ([taste] of myself) set restaurant? ([restaurant?] of myself) set orig-x ([orig-x] of myself) set orig-y ([orig-y] of myself) set pcolor ([pcolor] of myself) sprout-vacancy-lights 1[ set shape "square" ;; this will act as the restaurant's vacancy light! set color white set size .8 set label-color black ] ] set capacity t-capacity set taste t-taste set restaurant? t-restaurant? set orig-x t-orig-x set orig-y t-orig-y set pcolor t-pcolor ] ] end
There is only one version of this model, created over 13 years ago by Taiyo Sogawa.
Attached files
No files
This model does not have any ancestors.
This model does not have any descendants.