Arooj preview image

1 collaborator

Default-person arooj shabbir (Author)


(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by everyone
Model was written in NetLogo 5.1.0 • Viewed 320 times • Downloaded 23 times • Run 0 times
Download the 'Arooj' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Inventory management is a critical problem in the supply chain management. Lots of analysis regarding the inventory dynamics in the supply chain system can be found in the literature of the operations research community. In this model, we explore a simplified network supply chain. There is one supplier, which has unlimited supply. There can be multiple distributors and retailers. Players order from upstream nodes and ship to downstream nodes. By selling goods, the players receive revenues. If players are not able to satisfy the demand, back-orders are created, the penalty costs occur. Also holding inventory incurs utility and maitenance costs. Players are striving to maximize their profit by wisely manage their ordering strategy and inventory policy.


Every day, a daily demand is imposed to each retailer. Retailers order from distributors, and distributors order from the supplier. We assume that all distributors and retailers are following the base-stock policy, that is: once the inventory position drops below the base-stock level, the player order the difference between the base-stock level and current inventory position; otherwise order nothing. The retailers will choose which distributor to order from according to the back-orders. The distributors need to allocate the available on-hand inventory to retailers, according to their respective quota. Once all the order, replenish, and ship activities are complished, we conclude the day and summarize the cost and revenue for each player. Then a new day starts.


Press "setup" button to establish the supply chain. Press "go" button to carry on the simulation.

"number-of-distributors" and "number-of-retailers" sliders adjust the number of distributors and retailers in the supply chain system.

"lead-time-supplier-distributor" indicates the number of days of supply delay between the supplier and distributors. Similarly, "lead-time-distributor-retailer" indicates the number of days of supply delay between distributors and retailers.

"initial-stock-distributor" and "initial-stock-retailer" are the initial inventory at the begining of the simulation for distributors and retailers, respectively.

"record-length" indicates how many recent day's demand history will be kept in record.

If ticks > "days-of-simulation", the program stops.

There are a chooser and several sliders for adjusting the generation mechanism of the daily demand. The monitor indicates today's demand.

The "total profit" and "on-hand inventory" plot the profit and on-hand stock level, respectively, at the current day of simulation for all players.


The fluctuation of the on-hand inventory level at the distributors and retailers. It is said the fluctuation would propogate from downstream to upstream, so-called bull-whip effect.


Users can adjust the lead times to see how this will affect the supply chain.

Also, will the safety factors have significant influence on the supply chain?

How will different demand distributions matter?


In the current model, we assume that all the lead times are the same. Actually they can be different. This would cause desyncronization, which may lead to interesting results.

In the current model, we assume full connection. However, a retailer may not have connections with all the distributors. Will this create bias?

In the current model, we only consider 3 echelons. It may be interesting to extend to more echelons and more complicated supply chain configuration.


Wilensky, U. and Stroup, W. (2003). NetLogo HubNet Root Beer Game model. Center for Connected Learning and Computer-Based Modeling, Northwestern Institute on Complex Systems, Northwestern University, Evanston, IL.

Comments and Questions

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

Click to Run Model

globals [
  demand-today           ;; the demand occurs at all retailers everyday
  colors                 ;; colors for plot

breed [players player]

;; There are 2 types of directed links in the model
;; demand links for order placement, and supply links for shipment pipeline

directed-link-breed [supply-links supply-link]
supply-links-own [orders-filled pair-demand-link]

directed-link-breed [demand-links demand-link]
demand-links-own [orders-placed back-orders]

players-own [
  role             ;; 3 roles in the model: supplier, distributor, and retailer
  base-stock       ;; we assume players are operating under base-stock policy   
  inventory-position   ;; inventory equals to on-hand inventory + pipeline inventory - back-orders
  id-number         ;; id-number is used to distinguish players with the same role
  demand-history    ;; a list consisting of the demands in a few past days
  revenue           ;; revenue from selling the products
  safety-factor     ;; parameter determining to what extent the player want to keep safety inventory against demand uncertainty

to setup
  set colors [5 15 25 35 45 55 65 75 85 95 105 115 125 135 67 117 28 18 37]  ;; a list of 20 colors
  set colors shuffle colors   

to go
  if ticks >= days-of-simulation [stop]
  set demand-today daily-demand          ;; generate today's demand

to update-policy             ;; the players can update their inventory policy according to their demand record
  ask players with [role = "distributor"][
    set base-stock cal-base-stock-level demand-history lead-time-supplier-distributor
  ask players with [role = "retailer"][
    set base-stock cal-base-stock-level demand-history lead-time-distributor-retailer

;; Inventory operations
;; **************************

to place-order-to-up
  ask players with [role = "retailer" or role = "distributor"][
                                                                       ;; in this model, we assume all players are operating under base-stock policy
    let amount-to-order max list (base-stock - inventory-position) 0   ;; that is once the inventory position is below the base stock level, 
                                                                       ;; we order the quantity equal to the difference between inventory position and base stock level
                                                                       ;; otherwise, don't place any order

    ask my-out-demand-links [set orders-placed 0]                      ;; since in a network supply chain, a player can order from multiple upstream nodes
    ask who-to-order [set orders-placed amount-to-order]               ;; choose one node each time

to receive-order-from-up 
  ask players [
    if role = "distributor" or role = "retailer" [                       
      set last-received sum [first orders-filled] of my-in-supply-links     ;; take out the first item in the supply-link pipeline
      ask my-in-supply-links [set orders-filled but-first orders-filled]    ;; remove it from the pipeline
      set on-hand on-hand + last-received                                   ;; add it to the current on-hand inventory
    if role = "supplier" [set on-hand 10000]                                ;; we assume the supplier has unlimited supply

to process-order-from-down
  ask players [
    let new-orders 0                                        ;; for distributors and suppliers, new orders equal to the sum of the orders-placed of all in-demand-links
    if role = "distributor" or role = "supplier" [set new-orders sum [orders-placed] of my-in-demand-links]   
    if role = "retailer" [set new-orders demand-today]      ;; for retailers, new orders simply equal to today's demand
    set demand-history lput new-orders demand-history       ;; record the new-order in the demand history    
    set demand-history but-first demand-history             ;; delete the earliest demand history on the record, in order to keep the record length the same
    let orders-requested new-orders + backlog               ;; besides new orders, back-orders also need to be satisfied
    let orders-to-ship min list orders-requested on-hand    ;; if there is sufficient inventory, ship the requested amount
                                                            ;; if not sufficient inventory, ship whatever on-hand
    if role = "distributor" [set revenue revenue + 2 * orders-to-ship]    ;; revenue for distributors is 2 for each unit shipped
    if role = "retailer" [set revenue revenue + 3 * orders-to-ship]       ;; revenue for is 3 for each unit shipped
    set backlog max list 0 (backlog - on-hand + new-orders)    ;; the unsatisfied demand is counted as backlog (or back-orders)
    let rest-amount orders-to-ship       ;; allocate total shipping amount to each downstream node
    foreach sort my-out-supply-links [
      ask ? [                                    ;; quota to each supply link is proportional the sum of back-orders and new orders of the pair demand link
        let quota sum [back-orders] of pair-demand-link + sum [orders-placed] of pair-demand-link   
        let ship-to-this-link 0                  ;; if no order, ship nothing, and put 0 in the supply link
        if orders-requested > 0 [                ;; if positive order, ship according to the quota
          set ship-to-this-link min list ceiling (quota * orders-to-ship / orders-requested) rest-amount
        ]                                        ;; note that we use ceiling to guarantee the integrity of the shipping quantity
        set rest-amount rest-amount - ship-to-this-link  
        set orders-filled lput ship-to-this-link orders-filled    ;; put the ship quantity at the last place of the supply pipeline
        ask pair-demand-link [set back-orders max list 0 (quota - ship-to-this-link)]  ;; update the back-orders in the pair demand link
    set on-hand on-hand - orders-to-ship    ;; reduce the shipped quantity from the on-hand inventory

to summarize
  ask players [
    let pipeline sum [sum orders-filled] of my-in-supply-links    ;; calculate the pipeline inventory (inventory in-transit) for each player
    set inventory-position on-hand + pipeline - backlog           ;; recalculate the inventory position
    let cost-add (0.5 * on-hand + 2 * backlog)                    ;; calculate inventory holding cost and backlog penalty
    set cost cost + cost-add                                      ;; update the cost
  ask players with [role = "distributor" or role = "retailer"] [  ;; plots

;; ****************************

to-report y-locations [number]         ;; report a list of y-coordinates that would evenly distribute the "number" players on y-axis
  let y-list []

  let interval round ((2 * (max-pycor - 3) + 1) / (number + 1))
  let current-pos (- max-pycor + 3 + interval)
  repeat number [
    set y-list lput current-pos y-list
    set current-pos current-pos + interval
  report y-list

to layout
  set-default-shape players "circle"
  set-default-shape links "arc"

  create-players 1 [
    setxy -10 0
    set color red
    set role "supplier"
    set size 5                ;; the size of the supplier won't be updated in the simulation
  ask patches with [pxcor = 0 and (member? pycor y-locations num-of-distributors)] [  ;; evenly layout the distributors in the middle
    sprout-players 1 [
      set color blue
      set role "distributor"      
  ask patches with [pxcor = 10 and (member? pycor y-locations num-of-retailers)] [ ;; evenly layout the retailers on the right
    sprout-players 1 [
      set color green
      set role "retailer"
  let d-number 1
  foreach sort players with [role = "distributor"][   ;; assign each distributor an id-number, and label them with the id-number
    ask ?[
      set label word "D-" d-number
      set id-number d-number
      set d-number d-number + 1
  let r-number 1
  foreach sort players with [role = "retailer"][    ;; assign each retailer an id-number, and label them with the id-number
    ask ?[
      set label word "R-" r-number
      set id-number r-number
      set r-number r-number + 1
  let index 0
  foreach sort players with [role = "distributor" or role = "retailer"][
    ask ?[
      set pen-color item index colors    ;; assign each distributor and retailer a different plot pen color
      set index index + 1
  ask players with [role = "retailer"] [
    create-demand-links-to players with [role = "distributor"]     ;; create demand and supply links between distributors and retailers
    create-supply-links-from players with [role = "distributor"]   
  ask players with [role = "distributor"] [
    create-demand-links-to players with [role = "supplier"]        ;; create demand and supply links between supplier and distributors
    create-supply-links-from players with [role = "supplier"] 
  ask supply-links [                                  ;; define the pair demand link of each supply link, the link with the same ends
    set pair-demand-link demand-links with [end1 = [end2] of myself and end2 = [end1] of myself]

to initialize
  ask players [
    if role = "distributor" [
      set base-stock initial-stock-distributor   ;; set the initial base-stock level and on-hand inventory to "initial-stock-distributor"
      set on-hand initial-stock-distributor
      ask my-out-demand-links [
        set orders-placed 0 
        set back-orders 0
      ;; create a list with all elements equal to 0, with the length equals to "lead-time-supplier-distributor"
      ;; representing the supply pipeline between the supplier and the distributor
      ask my-in-supply-links [set orders-filled n-values lead-time-supplier-distributor [0]]  
    if role = "retailer" [
      set base-stock initial-stock-retailer
      set on-hand initial-stock-retailer
      ask my-out-demand-links [
        set orders-placed 0
        set back-orders random 0
      ;; create a list with all elements equal to 0, with the length equals to "lead-time-distributor-retailer"
      ;; representing the supply pipeline between the distributor and the retailer
      ask my-in-supply-links [set orders-filled n-values lead-time-distributor-retailer [0]]
    if role = "supplier"[
      set on-hand 10000
    set backlog 0
    set inventory-position on-hand - backlog
  ask players [    ;; randomly assign the safety-factor to players
    set cost 0     ;; the higher safety factor  means that the player is willing to keep higher safety inventory against the demand uncertainty
    set revenue 0                                    
    set safety-factor 1.5 + random-float 1
    set demand-history n-values record-length [""]  ;; set the demand history as a list with empty elements, with the length equals to "record-length"

to resize-shape    ;; visualize the on-hand stock via size of the turtle
  ask players with [role = "distributor" or role = "retailer"][
    set size 0.5 * (sqrt on-hand)          

to reset-plots          ;; clear all plots and create plot pens for each player
  ask players with [role = "distributor" or role = "retailer"][

to create-plot-pen [my-plot]
  set-current-plot my-plot
  create-temporary-plot-pen label  ;; name the plot pen with the player's label
  set-plot-pen-color pen-color

to create-plot-pens
  create-plot-pen "total profit"       ;; one plot for total profit
  create-plot-pen "on-hand inventory"  ;; one plot for on-hand inventory level

to plot-profit
  set-current-plot "total profit"
  set-current-plot-pen label
  plot revenue - cost

to plot-on-hand-inventory
  set-current-plot "on-hand inventory"
  set-current-plot-pen label
  plot on-hand

;; Demand distribution generation
;; **************************************

to-report daily-demand                ;; we design three mechanisms for generating the daily demand, which can be chosen in the chooser
  if distribution = "deterministic"
    [report deterministic-demand]     ;; deterministic demand means the demand is constant, there is no uncertainty      
  if distribution = "poisson"         ;; poisson demand means that the daily demand follows Poisson distribution
    [report random-poisson mean-for-poisson]             
  if distribution = "normal"          ;; normal demand means that the daily demand follows truncated normal distribution (modified in this model)
    [report truncated-normal mean-for-normal std-for-normal lower-bound-for-normal upper-bound-for-normal]   

to-report truncated-normal [mean-value std-value min-value max-value]    ;; there are 4 parameters for the truncated normal distribution
  let random-num random-normal mean-value std-value                      ;; we first generate a random-normal number according to the mean value and standard-deviation value
  ifelse random-num > max-value or random-num < min-value                
  [report round (min-value + random-float (max-value - min-value))]      ;; if the value is beyond the min-value and max-value, report a random number within the range
  [report round random-num]                                              ;; if the value is within the min-value and max-value, report the rounding of this number
;; ***************************************************************

to-report cal-base-stock-level [demand-list delay]     ;; calculate base-stock based on demand-history
  let numbers filter is-number? demand-list            ;; during the first few days, not all the elements in the demand history are numbers, but ""
  let mean-value mean numbers                          ;; calculate mean value
  let std 0
  if length numbers >= 2[                              ;; calculate the standard deviation of the demand history
    set std standard-deviation numbers
                                                       ;; according to inventory theories, the base-stock level is usually calculate according to mean and std and supply delays                                  
  report round (mean-value * (delay + 1) + safety-factor * std * (sqrt (delay + 1)))  ;; "+1" because of the order processing delay

to-report who-to-order  ;; report the demand link that has the lowest back-orders, so that the player will choose to order from this one
  let min-back-order min [back-orders] of my-out-demand-links  ;; find out the minimum back-order
  let sorted-links []                         ;; prepare an empty list
  foreach sort my-out-demand-links [          ;; if the back-orders of the demand links equals to the minimum back-order
    ask ? [                                   ;; add the demand link to sorted-links list
      if back-orders = min-back-order [set sorted-links lput self sorted-links]
  ifelse member? current-supplier sorted-links [   ;; if the current-supplier (actually the corresponding demand link) is among the demand links with the minimum back-order 
    report current-supplier                        ;; choose the current supplier due to customer loyalty
  let chosen-one one-of sorted-links               ;; if not, choose one from the demand links with the minimum back-order
  set current-supplier chosen-one                  ;; then transfer the supplier to this one
  report chosen-one                               

There is only one version of this model, created over 9 years ago by arooj shabbir.

Attached files

File Type Description Last updated
Arooj.png preview Preview for 'Arooj' over 9 years ago, by arooj shabbir Download

This model does not have any ancestors.

This model does not have any descendants.