Supply Chain

Supply Chain preview image

1 collaborator

Gil Alvaro Gil (Author)

Tags

logistics 

Tagged by Alvaro Gil about 5 years ago

supply chain 

Tagged by Alvaro Gil about 5 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 5.0 • Viewed 10236 times • Downloaded 657 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.)


## WHAT IS IT?

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.

## HOW IT WORKS

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.

## HOW TO USE IT

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.

## THINGS TO NOTICE

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.

## THINGS TO TRY

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.

## EXTENDING THE MODEL

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.

## CREDITS AND REFERENCES

Developped by Alvaro Gil at the Polytechnic School of Motreal alvaro.gil@polymtl.ca

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.

alvaro.gil@polymtl.ca

About the NetLogo software

- Wilensky, U. (1999). NetLogo. http://ccl.northwestern.edu/netlogo/. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.

## COPYRIGHT NOTICE

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

Visit

http://aquaponicscenter.blogspot.com/

Posted almost 2 years ago

Click to Run Model

extensions [
  matrix 
  table]

globals [
  safety_values
  watching
  promotion
  stocks_h
  costs_h
  ret_list]

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

turtles-own [demand stock strategy]

Factories-own [
  production_rate
  reorder_point
  orders
  available_stock
  clients
  daily_sales
  sales
  lost_sales
  forecast
  holding_cost
  order_cost
  total_cost
]

distributors-own [
  EOQ
  next_review
  reorder_point
  orders
  available_stock
  suppliers
  supplier_score
  supplier0
  clients
  daily_sales
  sales
  lost_sales
  forecast
  placed_orders
  holding_cost
  order_cost
  total_cost
]

retailers-own [
  EOQ
  next_review
  reorder_point
  suppliers
  supplier_score
  supplier0
  clients
  daily_sales
  sales
  lost_sales
  forecast
  placed_orders
  holding_cost
  order_cost
  total_cost
]

customers-own [
  next_review
  daily
  suppliers
  supplier_score
  supplier0
]

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.)
  __clear-all-and-reset-ticks
  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]
  find_nearest
  update_clients 0
  update_market
  update_clients 0
  setup_parameters
  create_network
  update_plots
end 

to go
  send_products
  buy_products
  main_sequence
  update_clients 1
  create_network
  update_plots
  purge
  evaluate_results
  print_watch
  tick                 ;Next Day
end 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; 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
end 

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]
end 

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])]]
end 

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")]
end 

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"
    clear-plot
    foreach dd
    [plot ?]]
  [ask links [die]
    set-current-plot "Clients per Retailer"
    clear-plot]
end 

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)
  ]
end 

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

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

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]]
  ]
end 

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 [
    update_sales
    if strategy != 3
    [set next_review ticks + 1]]
end 

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
end 

to main_sequence
  ask retailers [
    update_forecast
    place_orders
    update_costs]
  ask distributors [
    update_sales
    update_forecast
    place_orders
    update_costs]
  ask factories [
    update_sales
    if stock < reorder_point
    [set stock stock + production_rate]
    update_forecast
    update_costs]
  ask customers [update_demand]
end 

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)
end 

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)
  ]
end 

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
    reset-perspective]
end 

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]
  ]
end 

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]]
  ]
end 

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]
end 

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
end 

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

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)]
 ]
end  

to update_plots
  set-current-plot "Daily Stock"
  let s []
  ;Customers
  set-current-plot-pen "Customers"
  plot sum([stock] of Customers)
  ;Retailers
  set-current-plot-pen "Retailers"
  plot sum([stock] of retailers)
  set s lput(sum([stock] of retailers)) s
  ;Distributors
  set-current-plot-pen "Distributors"
  plot sum([stock] of distributors)
  set s lput(sum([stock] of distributors)) s
  ;Factories
  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)
end 

There are 2 versions of this model.

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

Attached files

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

This model does not have any ancestors.

This model does not have any descendants.