Customer Stores Choice Model

Customer Stores Choice Model preview image

1 collaborator

Profile Sachin Yadav (Author)

Tags

choice 

Tagged by Sachin Yadav almost 3 years ago

consumer behaviour 

Tagged by Sachin Yadav almost 3 years ago

consumer demand 

Tagged by Sachin Yadav almost 3 years ago

consumers 

Tagged by Sachin Yadav almost 3 years ago

crowding at storesp 

Tagged by Sachin Yadav almost 3 years ago

customer 

Tagged by Sachin Yadav almost 3 years ago

customer distribution 

Tagged by Sachin Yadav almost 3 years ago

customer retention. 

Tagged by Sachin Yadav almost 3 years ago

customer satisfaction 

Tagged by Sachin Yadav almost 3 years ago

el farol 

Tagged by Sachin Yadav almost 3 years ago

logistics 

Tagged by Sachin Yadav almost 3 years ago

minority game 

Tagged by Sachin Yadav almost 3 years ago

restaurant problem 

Tagged by Sachin Yadav almost 3 years ago

retail competitionb 

Tagged by Sachin Yadav almost 3 years ago

shops 

Tagged by Sachin Yadav almost 3 years ago

store inventory 

Tagged by Sachin Yadav almost 3 years ago

store location 

Tagged by Sachin Yadav almost 3 years ago

stores 

Tagged by Sachin Yadav almost 3 years ago

supply chain 

Tagged by Sachin Yadav almost 3 years ago

waiting customers 

Tagged by Sachin Yadav almost 3 years ago

Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.2.0 • Viewed 747 times • Downloaded 80 times • Run 0 times
Download the 'Customer Stores Choice 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.)


Comments and Questions

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

Click to Run Model

breed [persons person]
breed [stores store]
breed [houses house]
;; the start-time (unhappiness start-time) is the first time when each customer have visited the target store at least once
;; the unhappiness-values-list keeps track of the unhappiness values of the population of the customers for calculation of standard-deviation
globals [start-time unhappiness-values-list]

persons-own [house-id home-xcor home-ycor
  ;; who-number of the home belonging to person, the x-coordinate and y-coordinate of the home
  store-travel-time-list store-visit-count-list store-total-waiting-time-list
  ;; store-travel-time-list contains the list of travel-distance from home to each store, store-visit-count-list contains the total number of visits by the person to each store
  ;; store-waiting-time-list contains the total waiting time for each store in the past visits of the person
  rest-time wait-time demand target-store-id
  ;; how much time the person will rest at home after returning from store
  ;; what is the quantity of the item that person requires in current visit to store
  ;; in the beginning of journey, the person decides which store to visit, the who of target store is saved in target-store-id
  at-home? at-store? travelling-to-store? travelling-to-home?]
  ;; the state variables, at-home is true if the person is at home, travelling-to-store if on way to store, travelling-to-home if on way to home, at-store if at store currently
stores-own [quantity]
;; every store keeps track of its current quantity

;; Reports the current average-unhappiness of the population
;; A person's unhappiness for a given store = Avg. Waiting Time at the store + Travel Time for the store (proportional to distance of store from home)
;; A person's unhappiness is counted towards average unhappiness, only when the person has visited the current targeted store at least once.
;; ^ This is to avoid bad unhappiness values when the person is yet to experience the target store atleast once

to-report average-unhappiness
  ;; Initialize the list for the unhappiness values of the customers
  set unhappiness-values-list []
  ;; The number of customers which have actually experienced the target-store at least once
  let actual-num-consumers 0
  ask persons [
    ;; If the person has visited the target store at least once
    if (item target-store-id store-visit-count-list) > 0
    [
      ;; insert its unhappiness value in the unhappiness list for the population
      set unhappiness-values-list lput store-unhappiness target-store-id unhappiness-values-list
      set actual-num-consumers actual-num-consumers + 1 ]
  ]
  ;; If all of the customers have atleast experienced their current target store at least once, then set the current time as the start-time
  if actual-num-consumers = num-consumers and start-time = 0 [set start-time ticks]

  ;; color the customers and houses as per the unhappiness distribution
  ;; report the standard-deviation and mean of the unhappiness if the actual numbers of customers are greater than 2
  if (actual-num-consumers >= 2)
  [
    let std-dev-unhappiness standard-deviation unhappiness-values-list
    let mean-unhappiness mean unhappiness-values-list
    ;;set the colors of the customer and house agents
    set-customer-unhappiness-colors std-dev-unhappiness mean-unhappiness
    ;; If the user has turned ON the visual tool to show the unhappiness distribution over the patches, then color the patches accordingly
    ;; otherwise set all the patches to turquoise color
    ifelse (show-unhappiness-terrain?) [show-unhappiness-terrain] [ ask patches [set pcolor turquoise] ]
  ]
  ;; report the average unhappiness value
  ifelse actual-num-consumers > 0
  [report mean unhappiness-values-list]
  [report 0]
end 

;; sets the color of the customers and houses as per the current unhappiness value in the population distribution

to set-customer-unhappiness-colors [std-dev mean-val]
  ask persons [
    ;; get the unhappiness value of the customer
    let person-unhappiness store-unhappiness target-store-id
    ;; red color for person with unhappiness more than mean value + standard-deviation
    (ifelse (person-unhappiness >= mean-val + std-dev) [set color red]
      ;; orange color for person with unhappiness above mean
    (person-unhappiness >= mean-val) [set color orange]
      ;; sky color for unhappiness below the mean-value - standard deviation, the happiest of the customers
    (person-unhappiness < mean-val - std-dev) [set color sky]
      ;; rest green color for below mean
    [ set color green])
    ;; set the same color for the house as of the associated customer
    ask house house-id [set color [color] of myself]
  ]
end 

;; set the color of the patches as per the color of the nearest house (denoting the unhappiness value of customer residing in the region)

to show-unhappiness-terrain
  ask patches [
    ;; local variable to store the new color value of the patch
    let my-new-color 0
    ;; get the color of the nearest house to the patch
    ask houses with-min [distance myself]
    [
      set my-new-color [color] of self
    ]
    ;; set a lighter tone for the patch color
    set pcolor my-new-color + 2
  ]
end 

;; reports the first time, when all of the customers have experienced their target store atleast once

to-report unhappiness-start-time
  report start-time
end 

to setup
  clear-all
  ask patches [set pcolor turquoise]
  ;; initialize the unhappiness start-time to 0
  set start-time 0
  ;; setup the stores in the grid
  setup-stores-initial

  ;; setup the persons in the grid
  setup-homes-and-consumers

  ;; initialize the lists and initial state variables for the persons
  ask persons [ initialize-person-lists-and-state ]
  reset-ticks
end 

;; if we want keep the location of stores same, but want to try a new location of consumers

to setup-consumers
  clear-all-plots
  ask patches [set pcolor turquoise]
  ;; initialize the unhappiness start-time to 0
  set start-time 0
  ;; kill all the persons and houses and generate a new set of customers and houses with different location
  ask persons [die]
  ask houses [die]
  ;; reset the quantity in the stores
  ask stores [set quantity store-capacity]
  ;; generate the customer and house pairs in the grid
  setup-homes-and-consumers
  ;; intialize the lists for each consumer
  ask persons [initialize-person-lists-and-state]
  reset-ticks
end 

;; if we want to keep the same location of consumers, but want to try a new location for shops

to setup-stores
  clear-all-plots
  ;; initialize the unhappiness start-time to 0
  set start-time 0
  ;; set a unifrom random location of the stores
  ;; intially the inventory (quantity) at each store is full
  ask stores [
    setxy random-xcor random-ycor
    set quantity store-capacity
  ]
  ;; initialize the list and state variables of the customers
  ask persons [initialize-person-lists-and-state]
  reset-ticks
end 

;; create the stores in the grid

to setup-stores-initial
    create-stores num-stores [
    setxy random-xcor random-ycor
    set shape "building store"
    set color yellow
    set size 1.5
    ;; intially the inventory (quantity) at each store is full
    set quantity store-capacity
  ]
end 

;; move each of the store to the average coordinate of its current customers

to move-shops-to-customers
  ask stores [
    let num-customers count link-neighbors
    let mean-x-customer mean [xcor] of link-neighbors
    let mean-y-customer mean [ycor] of link-neighbors
    ;; move the store to the mean coordian
    setxy mean-x-customer mean-y-customer
  ]
  reset-consumers
end 

;; move the store to the unhappiness weighted mean coordinate of its current customers

to move-shops-to-unhappiness-customers
  ask stores [
    let current-store-id [who] of self
    ;; the total unhappiness of current store customers
    let total-customer-unhappiness 0
    let mean-unhappiness-x-customer 0
    let mean-unhappiness-y-customer 0
    ;; ask the houses of its customers
    ask link-neighbors[
      let current-house-id [who] of self
      ;; get the customer who is associated with this house
      let person-here persons with [house-id = current-house-id]
      ;; ask the customer associated with this house
      ask person-here
      [
        let unhappiness-value store-unhappiness current-store-id
        ;; take the weigted x and y coordinate of the customer
        set mean-unhappiness-x-customer  mean-unhappiness-x-customer + (xcor * unhappiness-value)
        set mean-unhappiness-y-customer  mean-unhappiness-y-customer + (ycor * unhappiness-value)
        set total-customer-unhappiness total-customer-unhappiness + unhappiness-value
      ]
    ]
    ;; finally get the unhappiness weighted customer coordinates
    set mean-unhappiness-x-customer mean-unhappiness-x-customer / total-customer-unhappiness
    set mean-unhappiness-y-customer mean-unhappiness-y-customer / total-customer-unhappiness

    setxy mean-unhappiness-x-customer mean-unhappiness-y-customer
  ]
  reset-consumers
end 

;; reset the customer variables and set the location to its home location
;; reset the quantity of the store as well

to reset-consumers
  clear-all-plots
  set start-time 0
  ;; reset the quantity in the stores
  ask stores [set quantity store-capacity]
  ;; intialize the lists for each consumer
  ask persons [initialize-person-lists-and-state]
  reset-ticks
end 

;; create the customer and the associated house pairs on the grid

to setup-homes-and-consumers
    ;; create persons/consumers
    create-persons num-consumers [
    setxy random-xcor random-ycor
    ;; the initial location will be the location of person's home as well
    set home-xcor xcor
    set home-ycor ycor
    set shape "person"
    set color blue
    ;; store the current person in local variable parent
    let parent self
    ;; ask the patch on the where the person is standing to create an agent of breed house
    ask patch-here[
      sprout-houses 1 [
        set shape "house"
        set color blue
        ;; store the who number of house in local variable of the associated customer
        let current-house-id who
        ;; ask the customer stored as parent, to set its house-id to the who number of this house
        ask parent [
          set house-id current-house-id
        ]
      ]
    ]
  ]
  ;; reset the unhappiness values of the population list
  set unhappiness-values-list []
end 

;; initializes the calling customer's lists and initial-state

to initialize-person-lists-and-state
    ;; calculate the travelling distance to each store
    set store-travel-time-list n-values num-stores distance-from-store
    ;; initialize visit count for each store to zero
    set store-visit-count-list n-values num-stores [i -> 0]
    ;; initialize the total waiting time for each store to zero
    set store-total-waiting-time-list n-values num-stores [i -> 0]
    ;; set the initial state of person as at home
    set at-home? true
    ;; initialize the rest-time of the person
    set rest-time random person-max-rest-time
    ;; place the person at associated house
    setxy home-xcor home-ycor
end 

;; reports the euclidean distance from calling customer's house to the store with given who number as store-id

to-report distance-from-store [store-id]
  let distance-to-store 0
  ;; store the distance from home to store in distance-to-store variable
  ask house house-id [ set distance-to-store distance store store-id]
  ;; resport the distance
  report distance-to-store
end 

;; reports the best store option for the calling customer depending on the unhappiness values
;; unhappiness for a store = distance-from-home + (average waiting time at the store)

to-report best-store-option
  ;; prepare the unhappiness value for each store and store in a local variable - list
  let store-unhappiness-list n-values num-stores store-unhappiness
  ;; find the minimum unhappiness value
  let min-unhappiness min store-unhappiness-list
  ;; report the index (who of the store in this case) with the given minimum unhappiness-value
  report position min-unhappiness store-unhappiness-list
end 

;; reports the unhappiness for a particular store for the calling customer
;; unhappiness for a store = distance-from-home + (average waiting time at the store)

to-report store-unhappiness [store-id]
  ;; initally unhappiness = distance-from-home
  let unhappiness item store-id store-travel-time-list
  ;; add average waiting time for the store to the unhappiness value, if the number of visits to the store > 0
  if (item store-id store-visit-count-list) > 0 [
    set unhappiness unhappiness + (item store-id store-total-waiting-time-list) / (item store-id store-visit-count-list)
  ]
  ;; report the unhappiness value
  report unhappiness
end 

;; display the inner influence circles for each store
;; every house strictly inside this radius is a customer to calling store only, not to any other store

to-report inner-influence-radius
  let current-store self
  ;; the list of the houses of the current customers of the store
  let current-store-link-neighbors link-neighbors
  ;; report the distance of the nearest home which is a customer of another store
  report min [distance current-store] of houses with [not member? self current-store-link-neighbors]
end 

;; the distance of the home of the farthest customer for the store
;; this is the radius of the star network of this

to-report outer-influence-radius
  let current-store self
  ;; report the distance of the home of the farthest customer
  report max [distance current-store] of link-neighbors
end 

to go
  ;; perform the following actions for each customer
  ask persons[run-consumer-finite-state-logic]
  ;; increase the quantity in each store by the supply-rate
  ask stores [
    set quantity quantity + supply-rate
    ;; if the quantity of the store goes above its capacity, set quantity to exactly its capacity
    if quantity > store-capacity [set quantity store-capacity]
  ]
  ;; clear all the previous drawings
  clear-drawing
  ;; display inner-circles if inner-influence-circles? switch is ON
  if inner-influence-circles? [display-inner-influence-circles]
  ;; display outer-circles if outer-influence-circles? switch is ON
  if outer-influence-circles? [display-outer-influence-circles]
  ;; hide links if show-links? switch if OFF
  ask links [set hidden? not show-links?]
  tick
end 

;; contains the logic of customer for the go procedure

to run-consumer-finite-state-logic
  ;; fetch the target store via the target-store-id
    let target-store store target-store-id
    (ifelse
      ;; if the person is currently inside home
      at-home? = true [
        ;; if the person at home doesn't need rest
        ifelse rest-time = 0 [
          ;; set demand to a random value over the range
          set demand random person-max-demand

          let person-home house house-id
          ;; kill the link with previous target-store
          ask target-store[
            let link-with-person-home link-with person-home
            if link-with-person-home != nobody [ ask link-with-person-home [die] ]
          ]
          ;; calculate the best store, as per the unhappiness values
          set target-store-id best-store-option
          ;; update the target-store local variable as well
          set target-store store target-store-id
          ;; create a link between updated target-store and home of the person
          ask target-store[create-link-with  person-home ask link-with person-home [set color red]]

          ;; set at-home to false, set travelling-to-store to true
          set at-home? false
          set travelling-to-store? true]
        ;; otherwise if the person requires rest, then person stays at home and rest-time is decreased by 1
        [set rest-time rest-time - 1]
      ]
      ;; if the person is on its way to store
      travelling-to-store? = true[
          ;; if reached the store (that is when distance from store is less or equal to one)
          ifelse distance target-store <= 1[
          ;; move inside the shop
          setxy [xcor] of target-store [ycor] of target-store
          ;; travelling-to-store is set to false and at-store set to true
            set travelling-to-store? false
            set at-store? true ]
        ;; if still far from store, then face towards the store and move 1 step forward
            [ face target-store fd 1]
       ]
      ;; if the person is inside store
      at-store? = true [
        ;; try to get the demand fulfilled
        ifelse demand > 0 [
         ;; initialize the wait-time if the quantity at store is less than the demand of person
        if [quantity] of target-store < demand [ set wait-time floor (( demand - [quantity] of target-store ) / supply-rate) ]
          ;; increase the store visit count and total waiting time for the store accordingly
          set store-visit-count-list replace-item target-store-id store-visit-count-list (item target-store-id store-visit-count-list + 1)
          set store-total-waiting-time-list replace-item target-store-id store-total-waiting-time-list (item target-store-id store-total-waiting-time-list + wait-time)
          let person-demand demand
          ;; update the quantity at the store and the demand is fulfilled, set it to zero
          ask target-store[set quantity quantity - person-demand]
          set demand 0]
        [
        ;; if waiting is over
        ifelse wait-time = 0 [
            ;; move outside the store and get on way back to home
          set at-store? false
          set travelling-to-home? true]
          ;; if still needs to wait, decrease wait-time by 1
          [set wait-time wait-time - 1]]
      ]
      ;; if is travelling to home
      travelling-to-home? = true [
        ;; if reached near home
        ifelse (distancexy home-xcor home-ycor) <= 1 [
          ;; move inside home and set travelling to home as false
          setxy home-xcor home-ycor
          set travelling-to-home? false
          ;; set a rest-time uniform random in range 1 to person-max-rest-time
          set rest-time random person-max-rest-time
          set at-home? true ]
        ;; if far from home, face towards home and move forward one step
        [ facexy home-xcor home-ycor fd 1]]
     )
end 

;; display the inner influence circle for the calling store-agent

to display-inner-influence-circles
  ask stores [
    let distance-influence inner-influence-radius
    stamp-circle "circle" distance-influence
  ]
end 

;; display the outer influence circles for the calling store-agent

to display-outer-influence-circles
    ask stores [
    let distance-influence outer-influence-radius
    stamp-circle "circle 3" distance-influence
  ]
end 

;; to draw the influence circles on the grid
;; it stamps a shape of given size as "distance-influence * 2"
;; parameters are drawing-shape, the shape of the stamp, distance-influence, the radius in case of circles

to stamp-circle [drawing-shape distance-influence]
  ;; store-xcor and store-ycor stores the coordinates of the current store
  let store-xcor xcor
  let store-ycor ycor
  ;; ask the patch-here to create a circle turle, then stamp and then die
  ask patch-here[
    sprout 1[
      ;; set the center of the turtle at the store
      setxy store-xcor store-ycor
      set shape drawing-shape
      ;; lighten the shade of the color
      set color color + 1
      ;; make the turtle half transparent
      set color lput 125 extract-rgb color
      ;; set appropriate turtle-size for the
      set size 2 * ( distance-influence )
      ;; mark the color impression of the turtle and make it die
      stamp
      die
    ]
  ]
end 

There are 3 versions of this model.

Uploaded by When Description Download
Sachin Yadav almost 3 years ago Remove Unhappiness Population Distribution Histogram Download this version
Sachin Yadav almost 3 years ago Update the Image Files in Info tab Download this version
Sachin Yadav almost 3 years ago Initial upload Download this version

Attached files

File Type Description Last updated
Customer Stores Choice Model.pdf pdf Research Paper almost 3 years ago, by Sachin Yadav Download
Customer Stores Choice Model.png preview Preview for 'Customer Stores Choice Model' almost 3 years ago, by Sachin Yadav Download
customer_logic.png png Customer Logic Flowchart almost 3 years ago, by Sachin Yadav Download
store_logic.png png Store Logic Flowchart almost 3 years ago, by Sachin Yadav Download

This model does not have any ancestors.

This model does not have any descendants.