Argyle St Model

No preview image

1 collaborator

Default-person Taiyo Sogawa (Author)

Tags

(This model has yet to be categorized with any tags)
Model group EECS 372-Spring 2011 | Visible to everyone | Changeable by the author
Model was written in NetLogo 4.1.3 • Viewed 314 times • Downloaded 22 times • Run 2 times
Download the 'Argyle St Model' modelDownload this modelEmbed this 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

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

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 almost 13 years ago by Taiyo Sogawa.

Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.