Supply Chain

Supply Chain preview image

1 collaborator

Gil Alvaro Gil (Author)



Tagged by Alvaro Gil almost 7 years ago

supply chain 

Tagged by Alvaro Gil almost 7 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 5.0 • Viewed 14619 times • Downloaded 911 times • Run 0 times
Download the 'Supply Chain' modelDownload this modelEmbed this model

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


This model is an artificial market with four types of participants. The first are the costumers who have a daily demand and according to their strategy can purchase daily or periodically if their stock is below some specific level. The second are the retailers who sell products to costumers and update their demand forecast by considering the sales and the stock rupture (lost sales). The third are the distributors (who follow a similar procedure) to send products to retailers. Finally, there are the factories who start producing once their inventory level is lower than some reorder point.

The model can help students and professionals to understand better the supply chain with a single product, and how simple changes as the promotions, can affect the stocks levels and the demand calculation with a considerable amplitude, which is know as the bullwhip effect.


The customers demand is normally distributed with a given standard deviation. Both the mean and the variability are user parameters. The inventory values (product cost, holding costs and order costs), are also parameters from the model. The user can also modify the number of agents. Finally, the clients� strategy and the retailers and distributors strategy are also parameters. At every day, the costumers can score the purchase experience (if there are some), so the next period the customers will choose the best supplier. At the beginning, the score is given by taking into account only the distance from retailers (the nearest retailer will be the supplier), but with the time, the agents could change this perspective by punishing the supplier if the sale is incomplete.

As to suppliers (retailers and distributors), they use linear regression for update their forecast and calculate the reorder point. If the stock is lower than this point, they place an order to their own supplier. If their strategy is (s,Q), they will only ask for the difference between the actual stock and the Economic Order Quantity (EOQ). If the strategy is (s,S), they will also consider the daily demand during the lead time. The last option is to repeat this last strategy but periodically.

The factories does the same estimation but for starting the production in a fix daily rate calculated at the beginning of the simulation.


The user should fix some values and play the model (I recommend at least 720 periods for having some stable results), then collect statistics and play again. Different values will result in different costs and stock levels which can be compared in the analysis and conclusions phase.


See how the stock levels for each type of participant are so different but at the same time they follow the same patron?, this is because the inventory theory, no matter what strategy the agents, it will always happen.


Try to create promotions at some moment. See how they affect the stock levels and the inventory costs. See also how some retailer can increase the clients� number and hence the sales with these activities.


It would be nice to improve the model with:

1. More sophisticated forecasting models

2. Add some operational costs to the suppliers, so the user could evaluate the profit of every business.

3. Add more products to the models. This will require some elasticity concept because the products could or could not be substitutes among them, so the availability and/or the price will affect the demand.

4. Finally, we can think in smarter suppliers, who update their strategy and also improve it, to compete and to increase the earnings.


Developped by Alvaro Gil at the Polytechnic School of Motreal

If you mention this model in an academic publication, we ask that you include these citations for the model itself:

- Gil, Alvaro (2012). Artificial supply chain. �cole Polytechnique de Montr�al.

About the NetLogo software

- Wilensky, U. (1999). NetLogo. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.


Copyright 2012 Alvaro Gil. All rights reserved.

Permission to use, modify or redistribute this model is hereby granted, provided that both of the following requirements are followed:

a) this copyright notice is included.

b) this model will not be redistributed for profit without permission from Alvaro Gil. Contact the author for appropriate licenses for redistribution for profit.

Comments and Questions


Posted over 3 years ago

Has anyone gotten this model to work??? (Question)

I have tried several times from multiple machines to download and run this model. Every time that I try it, I get an unspecified error when I attempt to extract the files from zip. I have also tried running it in NetLogo web, also without any luck. Does anyone have any suggestions???????? Thank you!

Posted 7 months ago

Where to download the model

Hello, Thanks for your comment. The model was developed in NetLogo 4.2, a very old version which I think needs some updates to run with the current version of the software. You can download the model with a presentation explaining the model functionality and how to build it step by step on the following link The documentation is in French though, it was made as part of a lecture class at the Montreal University back in 2012. My email is also there, you can write to me directly if you have any further questions. Good luck

Posted 7 months ago

Click to Run Model

extensions [

globals [

breed [factories factory]
breed [distributors distributor]
breed [retailers retailer]
breed [customers customer]

turtles-own [demand stock strategy]

Factories-own [

distributors-own [

retailers-own [

customers-own [

to setup
  ;; (for this model to work with NetLogo's new plotting features,
  ;; __clear-all-and-reset-ticks should be replaced with clear-all at
  ;; the beginning of your setup procedure and reset-ticks at the end
  ;; of the procedure.)
  ask patches [set pcolor white]
  set promotion [0 0 0]          ;Retailer 1, Impact 2, Until 3
  set stocks_h [] ;Customer, Retailer, Distributor, Factory
  set costs_h []  ;Retailer, Distributor, Factory
  set safety_values table:make
  table:put safety_values 0.50 0
  table:put safety_values 0.55 0.125661347
  table:put safety_values 0.60 0.253347103
  table:put safety_values 0.65 0.385320466
  table:put safety_values 0.70 0.524400513
  table:put safety_values 0.75 0.67448975
  table:put safety_values 0.80 0.841621234
  table:put safety_values 0.85 1.036433389
  table:put safety_values 0.90 1.281551566
  table:put safety_values 0.95 1.644853627
  create-Factories Fact [
   set size 6
   set color red
   set label (word "Factory " [who] of self "     ")
   set orders []
   let s read-from-string first(Inventory_Policy)
   ifelse s = 4
   [set strategy (random 3) + 1]
   [set strategy s]
  create-distributors Distr1 [
   set size 5
   set color blue
   set suppliers []
   set supplier_score []
   set orders []
   set placed_orders []
   set label (word "Distr." [who] of self "     ")
   let s read-from-string first(Inventory_Policy)
   ifelse s = 4
   [set strategy (random 3) + 1]
   [set strategy s]
  create-retailers Distr2 [
   set size 4
   set color green
   set suppliers []
   set supplier_score []
   set placed_orders []
   set label (word "Ret. " [who] of self "   ")
   let s read-from-string first(Inventory_Policy)
   ifelse s = 4
   [set strategy (random 3) + 1]
   [set strategy s]
  ask turtles with [breed != customers][
    set daily_sales []
    set clients []
    set sales []
    set lost_sales []
    set forecast []
    set holding_cost []
    set order_cost []
    set total_cost []]
  create-customers Clients_N [
   set size 1
   set color 3
   set suppliers []
   set supplier_score []
   set demand round(random-normal Demand_W DS_D)
   set daily round(demand / 7)
   let s read-from-string first(Customers_Strategy)
   ifelse s = 3
   [set strategy (random 2) + 1]
   [set strategy s]
  set-default-shape Factories "dist0"
  set-default-shape distributors "dist1"
  set-default-shape retailers "dist2"
  set-default-shape customers "person"
  ask turtles [find_patch]
  update_clients 0
  update_clients 0

to go
  update_clients 1
  tick                 ;Next Day

;;;;; SETUP SUBROUTINES ;;;;;;;;

to find_patch
  setxy random-xcor random-ycor
  while [any? other turtles-here]
      [find_patch]                 ; keeps running until each patron is alone on patch

to find_nearest  
  ask turtles with [breed != factories]
  [let d []
   if breed = customers [set d sort([who] of retailers)]
   if breed = retailers [set d sort([who] of distributors) ]
   if breed = distributors [set d sort([who] of factories) ] 
   foreach d 
     [let temp2 [] 
       set temp2 lput(?) temp2 
       set temp2 lput(distance turtle ?) temp2 
       set suppliers lput temp2 suppliers]
   set suppliers sort-by [last ?1 < last ?2] suppliers
   set supplier_score map [int(last ?) + int(((last ?) - int(last ?)) * 10) / 10] suppliers]

to update_clients [flag]
  ifelse flag = 0
  [ask turtles with [breed != factories] [
    let m min(supplier_score)
    let p position m supplier_score
    set supplier0 first(item p suppliers)]
  ask turtles with [breed != customers] [
    let n [who] of self 
    set clients sort([who] of turtles with [(breed = retailers or breed = distributors or breed = customers) and supplier0 = n])]
  ask turtles with [breed = distributors or breed = factories] [
    foreach clients [set orders lput [0 0] orders]]]
  [ask customers [
    let m min(supplier_score)
    let p position m supplier_score
    set supplier0 first(item p suppliers)]
  ask retailers [
    let n [who] of self 
    set clients sort([who] of turtles with [(breed = retailers or breed = distributors or breed = customers) and supplier0 = n])]]

to create_promotion
  ;Simple method: Increase de demand in some specific retailer choose for the user
  let list1 read-from-string user-input "Create a promotion [a b c] (retailer a, impact b (1 to 10), during c periods"
  ifelse is-list? list1 and length(list1) = 3
  [let p item 0 list1
  let i item 1 list1
  let c (item 2 list1) + ticks
  let l []
  set l lput(p) l
  set l lput(i) l
  set l lput(c) l
  set promotion l
  user-message (word "Today a promotion will occur at store " p)
  if Score_Retailers? = true
  [ask customers [let list2 map [first ?] suppliers
    let m position p list2
    set supplier_score (replace-item m supplier_score (item m supplier_score - (random-float item 1 list1)))]]
  [user-message (word "The array doen't have a valid format, pleas try again")]

to create_network
  ask links [die]
  ifelse Show_Network = true [
    ask customers [
      if supplier0 != nobody
      [create-link-to retailer supplier0
      [set color gray + 3]]]
    ask retailers [
      create-link-to distributor supplier0
      [set color green]] 
    ask distributors [
      create-link-to factory supplier0
      [set color blue]]
    set ret_list sort([who] of retailers)
    let dd []
    ;let ddd sort(retailers)
    foreach ret_list
    [set dd lput(count(links with [end2 = retailer ?])) dd]
    set-current-plot "Clients per Retailer"
    foreach dd
    [plot ?]]
  [ask links [die]
    set-current-plot "Clients per Retailer"

to setup_parameters
  ask customers [
    set stock random demand   
  ask retailers [
    set stock round(sum([demand] of customers) / count(retailers)) * 5      ;All agents of the same type starts with the same stock
    set demand mean([daily] of customers) * length(clients) * 1
  ask distributors [
    set stock round(sum([stock] of retailers)) * .5    ;All agents of the same type starts with the same stock
    set demand mean([demand] of retailers) * length(clients) * 1
  ask Factories [
    set stock round(sum([stock] of distributors))
    set production_rate round(sum([demand] of customers) * 10)

;;;;;;; GO SUBROUTINES ;;;;;;;;;

to update_market
  ask turtles with [breed != customers and clients = []] [die]

to send_products
  ask turtles with [breed = distributors or breed = factories]
  [let list1 map [last ?] orders
   let list2 filter [? = ticks] list1
   if length(list2) > 0 and max(list2) > 0
   [let attending filter [last ? = ticks] orders
     set list2 []
     let list3 []
     foreach attending [
       set list2 lput(item (position ? orders) clients) list2
       set list3 lput(first(item(position ? orders) orders)) list3]
     let i 0
     while [i < length(list2)] [
     ask turtle (item i list2) [
       set stock (stock + item i list3)]
     set i i + 1]
     set i 0
     while [i < length(orders)]
     [if last(item i orders) = ticks
       [set orders replace-item i orders [0 0]]
       set i i + 1]]

to buy_products
  ;Customers go shopping according to their demand and their stock
  let list1 []
  ask turtles with [breed = retailers or breed = distributors or breed = factories ][
    set daily_sales [] 
    set lost_sales []]
  ask customers [
    let dem 0
    ifelse strategy = 1
    [set dem daily]
    [set dem round(daily * 4)]
    if promotion != [0 0 0] and member? who [clients] of retailer supplier0
    [set dem round(dem * random-float (item 1 promotion))]
    ifelse stock < dem and next_review = ticks [
        let agent [who] of self
        let d (dem + (dem - stock))
        ifelse [stock] of retailer (supplier0) >= d
        [ask retailer (supplier0) [
          set stock stock - d
          set daily_sales lput d daily_sales
          set lost_sales lput 0 lost_sales]
        let dd []
        set dd lput agent dd
        set dd lput d dd
        set list1 lput dd list1
        set stock stock - daily + d
        if Score_Retailers? = true
        [score_supplier who -0.01]]
        [ask retailer (supplier0) [set lost_sales lput dem lost_sales]
         if Score_Retailers? = true
         [score_supplier who 2 ]]
        ifelse strategy = 2
        [set next_review ticks + 3]
        [set next_review ticks + 1]]
      [ifelse stock - dem >= 0
        [set stock stock - dem]
        [set stock 0]
       set next_review ticks + 1 ]]
  ask retailers [
    if strategy != 3
    [set next_review ticks + 1]]

to update_sales
  let es sum(daily_sales)
  let ls sum(lost_sales)
  let l []
  set l lput es l
  set l lput ls l
  set sales lput l sales

to main_sequence
  ask retailers [
  ask distributors [
  ask factories [
    if stock < reorder_point
    [set stock stock + production_rate]
  ask customers [update_demand]

to update_forecast     
  ;Retailers, Distributors and Factories update their expectations
  let forecasting []
  set forecast []
  let temp_demand 0
  if length(sales) > 0 [set temp_demand map [sum(?)] sales]
  let ds 0
  ifelse (length(sales) > 2) and (max(temp_demand) != 0)
  [set forecast matrix:forecast-linear-growth (temp_demand)
    set ds standard-deviation temp_demand]
  [set forecast lput(round(demand / 7)) forecast
    set forecast lput(round(demand / 7)) forecast
    set forecast lput(0) forecast
    set forecast lput(0) forecast]
  let b item 1 forecast
  let a item 2 forecast
  let t length(sales)
  let i 1
  while [i <= 7] [
    set forecasting lput(t * a + b) forecasting
    set i i + 1
    set t t + 1]
  set demand round(sum(forecasting))
  if demand < 0 [set demand 0]
  let dailyd demand / 7
  let Lead_Time Lt0
  if breed = retailers [set Lead_Time Lt1]
  let z table:get safety_values SS_%
  if breed != factories
  [set EOQ round(sqrt(2 * demand * 52 * K / (HC * Product_cost)))]
  set reorder_point round(dailyd * Lead_Time + z * ds)

to print_watch
  if watching != 0
   show (word "At the period " ticks " the agent " watching " update its expectations :") 
   if ([breed] of turtle watching != customers) [
     show (word "Sales " [sales] of turtle watching)
     show (word "Forecast " [forecast] of turtle watching)]
   show (word "Demand " [demand] of turtle watching) 
   if ([breed] of turtle watching != customers and [breed] of turtle watching != factories) [
     show (word "EOQ " [EOQ]  of turtle watching)
     show (word "Reorder Point " [reorder_point] of turtle watching)]
   show (word "Stock " [stock] of turtle watching)

to follow_someone
  ifelse watching = 0
  [let l read-from-string user-input "What agent do you want to inspect?"
    set watching l
  watch turtle watching
  inspect turtle watching]
  [set watching 0

to place_orders
  ;Retailers and Distributors place orders according to their stock and forecasting
  if stock <= reorder_point [
    let p position [who] of self ([clients] of turtle supplier0)
    let actual_order first(item p ([orders] of turtle supplier0))
    if actual_order = 0 [
      let comande 0
      let lead_time Lt0
      if breed = retailers
      [set lead_time Lt1]
      ifelse strategy = 1
      [set comande round(EOQ - stock)]
      [set comande round(EOQ + (demand / 7) * lead_time)]
      let disp 0
      ask turtle supplier0 [
        let delivery ticks + lead_time
        let g []
        let ll 0
        ifelse stock > comande
        [set disp comande]
        [set disp stock
          set ll comande - disp]
        set g lput disp g
        set g lput delivery g
        set orders replace-item p orders g
        set stock stock - disp
        set daily_sales lput(disp) daily_sales
        set lost_sales lput(ll) lost_sales
      set placed_orders lput(disp) placed_orders]

to update_demand
  ifelse promotion = [0 0 0]
  [set demand round(random-normal Demand_W DS_D)
  set daily round(demand / 7)]
  [let p item 2 promotion
    if ticks = p [set promotion [0 0 0]]

to update_costs
  set holding_cost lput (HC * stock * Product_cost) holding_cost
  ifelse breed != factories
  [if (length(placed_orders) = 0) OR (length(placed_orders) != length(holding_cost))
  [set placed_orders lput 0 placed_orders]
  ifelse last(placed_orders) = 0
  [set order_cost lput 0 order_cost]
  [set order_cost lput K order_cost]
  set total_cost lput (last(order_cost) + last(holding_cost)) total_cost]
  [set total_cost lput (last(holding_cost)) total_cost]

to evaluate_results
  ;Collect statistics at the end of each period
  let l []
  ifelse first(promotion) = 0
  [set l lput (word ticks "-Reg") l]
  [set l lput (word ticks "-P-" item 0 promotion "-" item 1 promotion) l]
  set l lput(sum([stock] of customers)) l
  set l lput(sum([stock] of retailers)) l
  set l lput(sum([stock] of distributors)) l
  set l lput(sum([stock] of factories)) l
  set stocks_h l
  set l []
  let s 0
  foreach ([total_cost] of retailers) [set s s + (last(?))]
  set l lput(s) l
  set s 0
  foreach ([total_cost] of distributors) [set s s + (last(?))]
  set l lput(s) l
  set s 0
  foreach ([total_cost] of factories) [set s s + (last(?))]
  set l lput(s) l
  set costs_h l

to purge
  ask turtles with [breed != customers]
  [if length(sales) > 100
    [let l length(sales) 
      set sales sublist sales (l - 100) l

to score_supplier [a b]
 ;agent A, score B
 ask turtle a [
  let list1 map [first ?] suppliers
  let p position supplier0 list1
  if item p supplier_score + b >= 0
  [set supplier_score replace-item p supplier_score (item p supplier_score + b)]

to update_plots
  set-current-plot "Daily Stock"
  let s []
  set-current-plot-pen "Customers"
  plot sum([stock] of Customers)
  set-current-plot-pen "Retailers"
  plot sum([stock] of retailers)
  set s lput(sum([stock] of retailers)) s
  set-current-plot-pen "Distributors"
  plot sum([stock] of distributors)
  set s lput(sum([stock] of distributors)) s
  set-current-plot-pen "Factories"
  plot sum([stock] of Factories)
  set s lput(sum([stock] of Factories)) s
  ;set-plot-y-range 0 max(s)

There are 2 versions of this model.

Uploaded by When Description Download
Alvaro Gil over 5 years ago Updated file V.5.0 Download this version
Alvaro Gil almost 7 years ago Initial upload Download this version

Attached files

File Type Description Last updated
Jama-1.0.2.jar extension jama over 5 years ago, by Alvaro Gil Download
matrix.jar extension Matrix_jar over 5 years ago, by Alvaro Gil Download
Supply Chain.png preview Preview over 5 years ago, by Alvaro Gil Download
table.jar extension table extention over 5 years ago, by Alvaro Gil Download

This model does not have any ancestors.

This model does not have any descendants.