globals [ ; number-of-repeats round-counter run-counter ; consumers nOfConsumers reach ; shops totalDemand meanCapacity sdCapacity sdCapacityCost sdVariableCost sdUtilisationRate% ; adjustment variables nOfNewShops unmetDemand ; to draw demand and supply curves etc tempPrice demandCurve supplyCurve excessDemand ; trading totalSupply totalRevenue ; data collection lossmakingShops breakevenShops profitableShops sizeOfIndustry accumSizeOfIndustry accumSizeOfIndustry4 accumSizeOfIndustry8 accumSizeOfIndustry20 accumSizeOfIndustry28 accumSizeOfIndustry40 meanAccumSizeOfIndustry4 meanAccumSizeOfIndustry8 meanAccumSizeOfIndustry20 meanAccumSizeOfIndustry28 meanAccumSizeOfIndustry40 newShops accumNewShops accumNewShops4 accumNewShops8 accumNewShops20 accumNewShops28 accumNewShops40 meanAccumNewShops4 meanAccumNewShops8 meanAccumNewShops20 meanAccumNewShops28 meanAccumNewShops40 averagePrice accumAveragePrice accumAveragePrice4 accumAveragePrice8 accumAveragePrice20 accumAveragePrice28 accumAveragePrice40 meanAccumAveragePrice4 meanAccumAveragePrice8 meanAccumAveragePrice20 meanAccumAveragePrice28 meanAccumAveragePrice40 sdShopPrices accumSDShopPrices accumSDShopPrices4 accumSDShopPrices8 accumSDShopPrices20 accumSDShopPrices28 accumSDShopPrices40 meanAccumSDShopPrices4 meanAccumSDShopPrices8 meanAccumSDShopPrices20 meanAccumSDShopPrices28 meanAccumSDShopPrices40 totalQuantitySold accumQuantitySold accumQuantitySold4 accumQuantitySold8 accumQuantitySold20 accumQuantitySold28 accumQuantitySold40 meanAccumQuantitySold4 meanAccumQuantitySold8 meanAccumQuantitySold20 meanAccumQuantitySold28 meanAccumQuantitySold40 capacityOfIndustry accumCapacityOfIndustry accumCapacityOfIndustry4 accumCapacityOfIndustry8 accumCapacityOfIndustry20 accumCapacityOfIndustry28 accumCapacityOfIndustry40 meanAccumCapacityOfIndustry4 meanAccumCapacityOfIndustry8 meanAccumCapacityOfIndustry20 meanAccumCapacityOfIndustry28 meanAccumCapacityOfIndustry40 ] breed [consumers consumer] breed [shops shop] consumers-own [ nOfSuppliers wtp consumerType ownDemand pricePaid supplier purchase-history boughtThisRound spendingThisRound spending-history ] shops-own [ ownCapacity ownUtilisationRate ownCapacityCost ownFixedCosts ownVariableCost ownTotalCost ownMarkUp ownPrice shopType ownSupply customer ownLastDeal lastStock ownStock lastSales ownSales revenue pastProfit profit profit-history sales-history stock-history price-history capacity-history capacityIncrease utilisation-history birthdate ; round at which created competitors ] ;________________________________________________________________________________________________________________________________________________ to setup clear-all ask patches [set pcolor white] set nOfConsumers 1000 set accumQuantitySold4 [ ] set accumQuantitySold8 [ ] set accumQuantitySold20 [ ] set accumQuantitySold28 [ ] set accumQuantitySold40 [ ] set accumCapacityOfIndustry4 [ ] set accumCapacityOfIndustry8 [ ] set accumCapacityOfIndustry20 [ ] set accumCapacityOfIndustry28 [ ] set accumCapacityOfIndustry40 [ ] set accumAveragePrice4 [ ] set accumAveragePrice8 [ ] set accumAveragePrice20 [ ] set accumAveragePrice28 [ ] set accumAveragePrice40 [ ] set accumSDShopPrices4 [ ] set accumSDShopPrices8 [ ] set accumSDShopPrices20 [ ] set accumSDShopPrices28 [ ] set accumSDShopPrices40 [ ] set accumSizeOfIndustry4 [ ] set accumSizeOfIndustry8 [ ] set accumSizeOfIndustry20 [ ] set accumSizeOfIndustry28 [ ] set accumSizeOfIndustry40 [ ] set accumNewShops4 [ ] set accumNewShops8 [ ] set accumNewShops20 [ ] set accumNewShops28 [ ] set accumNewShops40 [ ] reset-ticks end ;-------------------------------------------------------------------------------------------------- to go repeat number-of-runs [ ; at start ot each run reset-globals repeat number-of-rounds [ set round-counter round-counter + 1 if round-counter = 1 [ ask consumers [ ifelse search = "About half" [ set nOfSuppliers count shops in-radius reach ] [ set nOfSuppliers "All" ] ] ] ifelse round-counter > 1 and remainder ( round-counter - 1 ) 4 = 0 [ make-yearly-adjustments ] [ make-quarterly-adjustments ] draw-demand-and-supply-curves ; has to be done at this stage otherwise does not work properly trade collect-data-at-end-of-round ] collect-data-at-end-of-run ] collect-data-at-end end ;____________________________________________________________________________________________________________________________________________________ ; PROCEDURES ;____________________________________________________________________________________________________________________________________________________ to reset-globals ; This cannot be done in setup because it needs to be done for each run. ; general set run-counter run-counter + 1 set round-counter 0 if search = "All" [ set reach 500 ] if search = "About half" [ set reach 125 ] clear-turtles ; consumers create-consumers nOfConsumers ; fixed at 1000 in set-up [ set shape "person" set color black set size 5 setxy random-pxcor random-pycor if any? other turtles-here [ let empty-patches patches with [ not any? turtles-here ] if not any? empty-patches [ show "Run out of empty patches!"] move-to one-of empty-patches ] set spending-history [ ] ; to check purchases etc set purchase-history [ ] ; to check purchases etc ] ; set willingness-to-pay (wtp:) gives random figure between 5 and 15 to ensure that all can afford the product ask consumers [ set wtp 5 + random 11 ] ; set totalDemand count consumers with [ wtp >= 10 ] ; shops set meanCapacity precision ( floor totalDemand / nOfShops ) 0 create-shops nOfShops [ define-shops ] ; to record results set accumQuantitySold [ ] set accumAveragePrice [ ] set accumSDShopPrices [ ] set accumSizeOfIndustry [ ] set accumCapacityOfIndustry [ ] set accumNewShops [ ] ; to draw demand and supply curves etc set tempPrice 0 set demandCurve 0 set supplyCurve 0 set excessDemand 0 end ;----------------------------------------------------------------------- to round-reset ask consumers [ set color black set supplier nobody set boughtThisRound "No" ] ask shops [ set color red set customer nobody set ownSupply 0 set ownStock 0 set ownLastDeal 0 set ownSales 0 set revenue 0 set profit 0 ] end ; ------------------------------------------------------------------------ to define-shops ; need to be able to call on this to create new shops ; is prefaced automatically by "ask shops". set shape "pentagon" set color red set size 7 setxy random-pxcor random-pycor if any? other turtles-here [ let empty-patches patches with [ not any? turtles-here ] if not any? empty-patches [ show "Run out of empty patches!"] move-to one-of empty-patches ] ifelse round-counter = 0 [ set birthdate round-counter + 1] [ set birthdate round-counter ] if scenario = "Perfect" ; all shops the same [ set ownCapacity meanCapacity set ownCapacityCost meanCapacityCost set ownVariableCost meanVariableCost set ownUtilisationRate meanUtilisationRate% ] if scenario = "Real" ; standard deviations set to 10% of means [ set ownCapacity precision ( random-normal meanCapacity ( meanCapacity * 0.1 ) ) 0 if ownCapacity = 0 [ set ownCapacity meanCapacity ] if ownCapacity > 1000 [ set owncapacity 1000 ] set ownCapacityCost precision ( random-normal meanCapacityCost ( meanCapacityCost * 0.1 ) ) 1 if ownCapacityCost = 0 [ set ownCapacityCost meanCapacityCost ] set ownVariableCost precision ( random-normal meanVariableCost ( meanVariableCost * 0.1 ) ) 1 if ownVariableCost = 0 [ set ownVariableCost meanVariableCost ] set ownUtilisationRate precision ( random-normal meanUtilisationRate% ( meanUtilisationRate% * 0.1 ) / 100 ) 2 if ownUtilisationRate > 1 [ set ownUtilisationRate 1 ] ] calculate-supply set ownFixedCosts precision ( ownCapacity * ownCapacityCost ) 1 ; markup set ownMarkUp precision ( ownCapacityCost / ownVariableCost ) 3 set ownPrice precision ( ownVariableCost * ( 1 + ownMarkUp ) ) 1 set price-history [ ] set profit-history [ ] set sales-history [ ] set stock-history [ ] set capacity-history [ ] set utilisation-history [ ] end ;--------------------------------------------------------- to draw-demand-and-supply-curves ; this ignores any restrictions on searching if run-counter = 1 and round-counter = 1 [ ; initialise set tempPrice 1 repeat 25 [ ; demand ; set price tempPrice set demandCurve count consumers with [ wtp >= tempPrice ] ; supply set supplyCurve ( sum [ ownSupply ] of shops with [ ownPrice <= tempPrice ] ) ; draw demand and supply curves set-current-plot "Demand and Supply at start of first run" set-plot-x-range 0 1000 set-plot-y-range 0 25 set-current-plot-pen "demand" plotxy demandCurve tempPrice set-current-plot-pen "supply" plotxy supplyCurve tempPrice ; roll forward set tempPrice tempPrice + 1 ] ] end ;----------------------------- to calculate-supply ; shops ; keep separate as used more than once! set ownSupply precision ( ownUtilisationRate * ownCapacity ) 0 end ;-------------------------- to trade ask shops [ set ownStock ownSupply set ownSales 0 ] set totalSupply sum [ ownSupply ] of shops ask consumers [ set boughtThisRound "No" set color black ] ; Consumers seek lowest price ; Need to set out group by group to ensure actions taken in correct order - otherwise can find shops selling stock they haven't got! ask consumers [ set supplier min-one-of shops in-radius reach with [ ownStock > 0 ] [ ownPrice ] go-shopping ] end ;--------------------------- to go-shopping if supplier != nobody and [ ownPrice ] of supplier <= wtp ; [ ask supplier [ set ownStock ownStock - 1 set ownSales ownSales + 1 set color blue ] ; consumer set pricePaid [ ownPrice ] of Supplier set boughtThisRound "Yes" set color green ] end ;-------------------------------- to make-quarterly-adjustments ; shops ; Each quarter change supply, price and variable costs according to sales ; Shops selling all their stock and operating below capacity, increase their utilisation rate by 10% ask shops with [ lastStock = 0 and ownUtilisationRate < 1 ] [ set ownUtilisationRate precision ( ownUtilisationRate * (1 + utilisationRateIncrease% / 100 )) 3 ] ; Shops not selling all their stock reduce their supply, costs, prices. ask shops with [ lastStock > 0 ] [ set ownStock precision ( ownCapacity - ( ownCapacity - lastSales ) / 2 ) 2 set ownUtilisationRate precision ( ownStock / ownCapacity ) 2 set competitors count other shops in-radius reach ; if monopoly, reduce price by 10% if competitors = 0 [ set ownPrice precision ( ownPrice * 0.9 ) 1 ] if competitors > 0 [ let competitorsPrice precision ( mean [ ownPrice ] of other shops in-radius reach ) 1 if ownPrice > competitorsPrice [ set ownPrice precision ( competitorsPrice ) 1 ] ] if ownMarkUp > 0.33 [ set ownMarkUp 0.33 ] set ownVariableCost precision ( ownPrice / ( 1 + ownMarkUp )) 1 ] ; to ensure that no shops supply above their capacity ask shops with [ ownUtilisationRate > 1 ] [ set ownUtilisationRate 1 ] ; recalculate supply ask shops [ calculate-supply ] end ;---------------------------------- to make-yearly-adjustments ; Shops ; Every year (i.e. every 4 quarters) i.e. round 5, 9 etc ; Exisiting shops change capacity according to profitability. ; Shops making a cumulative loss over the last 4 rounds die ask shops with [ pastProfit < 0 ] [ die ] ; Shops making a cumulative profit over the last 4 rounds and whose utilisation rate is less than 100%, increase their utilisation by the amount set by the utilisationRateIncrease% slider ask shops with [ pastProfit > 0 and ownUtilisationRate < 1 ] [ set ownUtilisationRate precision ( ownUtilisationRate * (1 + utilisationRateIncrease% / 100 ) ) 1 ] ; Shops making a profit over the last 4 rounds and whose utilisation rate is 100%, increase their capacity by the amount set by the capacityIncrease% slider ask shops with [ pastProfit > 0 and ownUtilisationRate = 1 ] [ set ownCapacity precision ( ( 1 + capacityIncrease% / 100 ) * ownCapacity ) 0 set capacityIncrease "Yes" ] ; to keep number of shops constant set nOfNewShops ( nOfShops - count shops ) if nOfNewShops > 0 [ create-shops nOfNewShops [ define-shops ] ] ask shops [ set pastProfit 0 ] ; reset pastProfit to 0 ; utilisation cannot exceed 1 ask shops with [ ownUtilisationRate > 1 ] [ set ownUtilisationRate 1 ] end ;________________________________________________________________________________________________________ ; RESULTS ;________________________________________________________________________________________________________ to collect-data-at-end-of-round ask shops [ set revenue precision ( ownPrice * ownSales) 0 set ownTotalCost precision (( ownVariableCost * ownSupply ) + ownFixedCosts ) 0 set profit precision ( revenue - ownTotalCost ) 0 set price-history lput ownPrice price-history set profit-history lput profit profit-history set sales-history lput ownSales sales-history set stock-history lput ownStock stock-history set capacity-history lput ownCapacity capacity-history set utilisation-history lput ownUtilisationRate utilisation-history set lastStock ownStock set lastSales ownsales set pastProfit profit + pastProfit ] ; prices and sales ; set accumEquilibPrice lput equilibriumPrice accumEquilibPrice set totalQuantitySold sum [ ownSales ] of shops set totalRevenue sum [ revenue ] of shops ifelse totalQuantitySold > 0 [ set averagePrice precision ( totalRevenue / totalQuantitySold ) 1 ] [ set averagePrice 0 ] set accumQuantitySold lput totalQuantitySold accumQuantitySold set accumAveragePrice lput averagePrice accumAveragePrice ifelse count shops > 1 [ set sdShopPrices precision ( standard-deviation [ ownPrice ] of shops ) 1 ] [ set sdShopPrices 0 ] set accumSDShopPrices lput sdShopPrices accumSDShopPrices ; capacity and size of industry set capacityOfIndustry sum [ ownCapacity ] of shops set accumCapacityOfIndustry lput capacityOfIndustry accumCapacityOfIndustry set sizeOfIndustry count shops set accumSizeOfIndustry lput sizeOfIndustry accumSizeOfIndustry set newShops ( count shops with [ birthdate > 1 ] ) set accumNewShops lput newShops accumNewShops if run-counter = 1 [ set-current-plot "Industry size" set-current-plot-pen "Size" plotxy round-counter sizeOfIndustry set-current-plot-pen "New" plotxy round-counter newShops set-current-plot "Average price" plotxy round-counter averagePrice set-current-plot "Price variation" plotxy round-counter sdShopPrices set-current-plot "Quantities" set-current-plot-pen "Sold" plotxy round-counter totalQuantitySold set-current-plot-pen "Capacity" plotxy round-counter capacityOfIndustry set-current-plot "Profit and loss" set-current-plot-pen "Loss" plotxy round-counter lossmakingShops set-current-plot-pen "BE" plotxy round-counter breakevenShops set-current-plot-pen "Profit" plotxy round-counter profitableShops ] end ; ----------------- to collect-data-at-end-of-run if number-of-rounds > 3 [ let averagePrice4 item 3 accumAveragePrice set accumAveragePrice4 ( lput averagePrice4 accumAveragePrice4 ) let sdShopPrices4 item 3 accumSDShopPrices set accumSDShopPrices4 ( lput sdShopPrices4 accumSDShopPrices4 ) let quantitySold4 item 3 accumQuantitySold set accumQuantitySold4 ( lput quantitySold4 accumQuantitySold4 ) let capacityOfIndustry4 item 3 accumCapacityOfIndustry set accumCapacityOfIndustry4 ( lput capacityOfIndustry4 accumCapacityOfIndustry4 ) let sizeOfIndustry4 item 3 accumSizeOfIndustry set accumSizeOfIndustry4 ( lput sizeOfIndustry4 accumSizeOfIndustry4 ) let newShops4 item 3 accumNewShops set accumNewShops4 ( lput newShops4 accumNewShops4 ) ] if number-of-rounds > 7 [ let averagePrice8 item 7 accumAveragePrice set accumAveragePrice8 ( lput averagePrice8 accumAveragePrice8 ) let sdShopPrices8 item 7 accumSDShopPrices set accumSDShopPrices8 ( lput sdShopPrices8 accumSDShopPrices8 ) let quantitySold8 item 7 accumQuantitySold set accumQuantitySold8 ( lput quantitySold8 accumQuantitySold8 ) let capacityOfIndustry8 item 7 accumCapacityOfIndustry set accumCapacityOfIndustry8 ( lput capacityOfIndustry8 accumCapacityOfIndustry8 ) let sizeOfIndustry8 item 7 accumSizeOfIndustry set accumSizeOfIndustry8 ( lput sizeOfIndustry8 accumSizeOfIndustry8 ) let newShops8 item 7 accumNewShops set accumNewShops8 ( lput newShops8 accumNewShops8 ) ] if number-of-rounds > 19 [ let averagePrice20 item 19 accumAveragePrice set accumAveragePrice20 ( lput averagePrice20 accumAveragePrice20 ) let sdShopPrices20 item 19 accumSDShopPrices set accumSDShopPrices20 ( lput sdShopPrices20 accumSDShopPrices20 ) let quantitySold20 item 19 accumQuantitySold set accumQuantitySold20 ( lput quantitySold20 accumQuantitySold20 ) let capacityOfIndustry20 item 19 accumCapacityOfIndustry set accumCapacityOfIndustry20 ( lput capacityOfIndustry20 accumCapacityOfIndustry20 ) let sizeOfIndustry20 item 19 accumSizeOfIndustry set accumSizeOfIndustry20 ( lput sizeOfIndustry20 accumSizeOfIndustry20 ) let newShops20 item 19 accumNewShops set accumNewShops20 ( lput newShops20 accumNewShops20) ] if number-of-rounds > 27 [ let averagePrice28 item 27 accumAveragePrice set accumAveragePrice28 ( lput averagePrice28 accumAveragePrice28 ) let sdShopPrices28 item 27 accumSDShopPrices set accumSDShopPrices28 ( lput sdShopPrices28 accumSDShopPrices28 ) let quantitySold28 item 27 accumQuantitySold set accumQuantitySold28 ( lput quantitySold28 accumQuantitySold28 ) let capacityOfIndustry28 item 27 accumCapacityOfIndustry set accumCapacityOfIndustry28 ( lput capacityOfIndustry28 accumCapacityOfIndustry28 ) let sizeOfIndustry28 item 27 accumSizeOfIndustry set accumSizeOfIndustry28 ( lput sizeOfIndustry28 accumSizeOfIndustry28 ) let newShops28 item 27 accumNewShops set accumNewShops28 ( lput newShops28 accumNewShops28) ] if number-of-rounds > 39 [ let averagePrice40 item 39 accumAveragePrice set accumAveragePrice40 ( lput averagePrice40 accumAveragePrice40 ) let sdShopPrices40 item 39 accumSDShopPrices set accumSDShopPrices40 ( lput sdShopPrices40 accumSDShopPrices40 ) let quantitySold40 item 39 accumQuantitySold set accumQuantitySold40 ( lput quantitySold40 accumQuantitySold40 ) let capacityOfIndustry40 item 39 accumCapacityOfIndustry set accumCapacityOfIndustry40 ( lput capacityOfIndustry40 accumCapacityOfIndustry40 ) let sizeOfIndustry40 item 39 accumSizeOfIndustry set accumSizeOfIndustry40 ( lput sizeOfIndustry40 accumSizeOfIndustry40 ) let newShops40 item 39 accumNewShops set accumNewShops40 ( lput newShops40 accumNewShops40 ) ] end ;-------------------------------------------------- to collect-data-at-end ;industry size if number-of-rounds > 3 [ set meanAccumSizeOfIndustry4 mean accumSizeOfIndustry4 set meanAccumAveragePrice4 mean accumAveragePrice4 set meanAccumSDShopPrices4 mean accumSDShopPrices4 set meanAccumQuantitySold4 mean accumQuantitySold4 set meanAccumCapacityOfIndustry4 mean accumCapacityOfIndustry4 set meanAccumNewShops4 mean accumNewShops4 ] if number-of-rounds > 7 [ set meanAccumSizeOfIndustry8 mean accumSizeOfIndustry8 set meanAccumAveragePrice8 mean accumAveragePrice8 set meanAccumSDShopPrices8 mean accumSDShopPrices8 set meanAccumQuantitySold8 mean accumQuantitySold8 set meanAccumCapacityOfIndustry8 mean accumCapacityOfIndustry8 set meanAccumNewShops8 mean accumNewShops8 ] if number-of-rounds > 19 [ set meanAccumSizeOfIndustry20 mean accumSizeOfIndustry20 set meanAccumAveragePrice20 mean accumAveragePrice20 set meanAccumSDShopPrices20 mean accumSDShopPrices20 set meanAccumQuantitySold20 mean accumQuantitySold20 set meanAccumCapacityOfIndustry20 mean accumCapacityOfIndustry20 set meanAccumNewShops20 mean accumNewShops20 ] if number-of-rounds > 27 [ set meanAccumSizeOfIndustry28 mean accumSizeOfIndustry28 set meanAccumAveragePrice28 mean accumAveragePrice28 set meanAccumSDShopPrices28 mean accumSDShopPrices28 set meanAccumQuantitySold28 mean accumQuantitySold28 set meanAccumCapacityOfIndustry28 mean accumCapacityOfIndustry28 set meanAccumNewShops28 mean accumNewShops28 ] if number-of-rounds > 39 [ set meanAccumSizeOfIndustry40 mean accumSizeOfIndustry40 set meanAccumAveragePrice40 mean accumAveragePrice40 set meanAccumSDShopPrices40 mean accumSDShopPrices40 set meanAccumQuantitySold40 mean accumQuantitySold40 set meanAccumCapacityOfIndustry40 mean accumCapacityOfIndustry40 set meanAccumNewShops40 mean accumNewShops40 ] file-open (word "Shops-"scenario"-"description".csv" ) file-print (word "Scenario " scenario ": Description " description) file-print " " file-print " " file-print ( word "Results over " number-of-runs " runs with " number-of-rounds " rounds") file-print " " file-print (word "Round 4" ) ifelse empty? accumAveragePrice8 [ file-print (word " No prices" ) ] [ file-type (word " Mean price = " precision ( meanAccumAveragePrice4 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumAveragePrice4 ) 1 ) ] ] ifelse empty? accumQuantitySold4 [ file-print (word " No sales" ) ] [ file-type (word " Mean quantity sold = " precision ( meanAccumQuantitySold4 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumQuantitySold4 ) 1 ) ] ] ifelse empty? accumSizeOfIndustry4 [ file-print (word " No shops" ) ] [ file-type (word " Mean industry size = " precision ( meanAccumSizeOfIndustry4 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumSizeOfIndustry4 ) 1 ) ] ] ifelse empty? accumNewShops4 [ file-print (word " No shops" ) ] [ file-type (word " Mean no. of new shops = " precision ( meanAccumNewShops4 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumNewShops4 ) 1 ) ] ] file-print (word "Round 8" ) ifelse empty? accumAveragePrice8 [ file-print (word " No prices" ) ] [ file-type (word " Mean price = " precision ( meanAccumAveragePrice8 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumAveragePrice8 ) 1 ) ] ] ifelse empty? accumQuantitySold8 [ file-print (word " No sales" ) ] [ file-type (word " Mean quantity sold = " precision ( meanAccumQuantitySold8 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumQuantitySold8 ) 1 ) ] ] ifelse empty? accumSizeOfIndustry8 [ file-print (word " No shops" ) ] [ file-type (word " Mean industry size = " precision ( meanAccumSizeOfIndustry8 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumSizeOfIndustry8 ) 1 ) ] ] ifelse empty? accumNewShops8 [ file-print (word " No shops" ) ] [ file-type (word " Mean no. of new shops = " precision ( meanAccumNewShops8 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumNewShops8 ) 1 ) ] ] file-print (word "Round 20" ) ifelse empty? accumAveragePrice20 [ file-print (word " No prices" ) ] [ file-type (word " Mean price = " precision ( meanAccumAveragePrice20 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumAveragePrice20 ) 1 ) ] ] ifelse empty? accumQuantitySold20 [ file-print (word " No sales" ) ] [ file-type (word " Mean quantity sold = " precision ( meanAccumQuantitySold20 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumQuantitySold20 ) 1 ) ] ] ifelse empty? accumSizeOfIndustry20 [ file-print (word " No shops" ) ] [ file-type (word " Mean industry size = " precision ( meanAccumSizeOfIndustry20 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumSizeOfIndustry20 ) 1 ) ] ] ifelse empty? accumNewShops20 [ file-print (word " No shops" ) ] [ file-type (word " Mean no. of new shops = " precision ( meanAccumNewShops20 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumNewShops20 ) 1 ) ] ] file-print (word "Round 28" ) ifelse empty? accumAveragePrice28 [ file-print (word " No prices" ) ] [ file-type (word " Mean price = " precision ( meanAccumAveragePrice28 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumAveragePrice28 ) 1 ) ] ] ifelse empty? accumQuantitySold28 [ file-print (word " No sales" ) ] [ file-type (word " Mean quantity sold = " precision ( meanAccumQuantitySold28 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumQuantitySold28 ) 1 ) ] ] ifelse empty? accumSizeOfIndustry28 [ file-print (word " No shops" ) ] [ file-type (word " Mean industry size = " precision ( meanAccumSizeOfIndustry28 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumSizeOfIndustry28 ) 1 ) ] ] ifelse empty? accumNewShops28 [ file-print (word " No shops" ) ] [ file-type (word " Mean no. of new shops = " precision ( meanAccumNewShops28 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumNewShops28 ) 1 ) ] ] file-print (word "Round 40" ) ifelse empty? accumAveragePrice40 [ file-print (word " No prices" ) ] [ file-type (word " Mean price = " precision ( mean accumAveragePrice40 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumAveragePrice40 ) 1 ) ] ] ifelse empty? accumQuantitySold40 [ file-print (word " No sales" ) ] [ file-type (word " Mean quantity sold = " precision ( meanAccumQuantitySold40 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumQuantitySold40 ) 1 ) ] ] ifelse empty? accumSizeOfIndustry40 [ file-print (word " No shops" ) ] [ file-type (word " Mean industry size = " precision ( meanAccumSizeOfIndustry40 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumSizeOfIndustry40 ) 1 ) ] ] ifelse empty? accumNewShops40 [ file-print (word " No shops" ) ] [ file-type (word " Mean no. of new shops = " precision ( meanAccumNewShops40 ) 1 ) if number-of-runs > 1 [ file-print (word " sd = " precision ( standard-deviation accumNewShops40 ) 1 ) ] ] export-all-plots (word "Shops-"scenario"-"description".csv" ) file-close end ;__________________________________________________________________________________________________________________________________________________ ;__________________________________________________________________________________________________________________________________________________ @#$#@#$#@ GRAPHICS-WINDOW 785 10 1179 423 158 157 1.213 1 10 1 1 1 0 1 1 1 -158 158 -157 157 0 0 1 ticks 30.0 BUTTON 3 10 67 43 Setup setup NIL 1 T OBSERVER NIL NIL NIL NIL 1 BUTTON 81 10 144 43 Go Go NIL 1 T OBSERVER NIL NIL NIL NIL 1 PLOT 411 29 763 270 Demand and Supply at start of first run Quantity Price 0.0 1000.0 0.0 25.0 true true "" "" PENS "supply" 1.0 0 -13345367 true "" "" "demand" 1.0 0 -13840069 true "" "" TEXTBOX 1075 431 1193 528 1 000 consumers (Green if bought)\nFirms = red blobs (Blue if traded)\n 12 0.0 1 MONITOR 137 180 230 225 NIL round-counter 0 1 11 CHOOSER 8 131 126 176 number-of-runs number-of-runs 1 2 10 30 2 MONITOR 137 128 229 173 NIL run-counter 0 1 11 CHOOSER 9 180 123 225 number-of-rounds number-of-rounds 1 2 4 8 20 40 5 PLOT 554 438 812 603 Industry size Rounds Shops 0.0 40.0 0.0 25.0 true true "" "" PENS "Size" 1.0 0 -16777216 true "" "" "New" 1.0 0 -2674135 true "" "" PLOT 10 443 275 611 Average price Round Price 0.0 40.0 0.0 30.0 true false "" "" PENS "default" 1.0 0 -16777216 true "" "" PLOT 279 443 548 610 Quantities Round Quantity 0.0 40.0 0.0 1000.0 true true "" "" PENS "Capacity" 1.0 0 -16777216 true "" "" "Sold" 1.0 0 -2674135 true "" "" MONITOR 821 478 921 523 min Fixed Costs min [ownFixedCosts] of shops 0 1 11 MONITOR 925 478 1029 523 max Fixed Costs max [ownFixedCosts] of shops 0 1 11 MONITOR 821 528 893 573 min Supply min [ownSupply] of shops 0 1 11 MONITOR 926 530 1000 575 max Supply max [ownSupply] of shops 0 1 11 MONITOR 819 625 881 670 min Price min [ ownPrice ] of shops 0 1 11 MONITOR 927 628 993 673 max Price max [ ownPrice ] of shops 0 1 11 MONITOR 819 577 908 622 min MarkUp% min [ownMarkUp ] of shops * 100 1 1 11 MONITOR 925 580 1019 625 max MarkUp% max [ownMarkUp ] of shops * 100 1 1 11 MONITOR 1064 521 1167 566 Utilisation 100% count shops with [ ownutilisationrate = 1 ] 0 1 11 MONITOR 819 428 914 473 min Capacity min [ owncapacity ] of shops 0 1 11 MONITOR 923 430 1011 475 max Capacity max [ owncapacity] of shops 0 1 11 MONITOR 1067 574 1167 619 NIL count shops 0 1 11 MONITOR 1035 630 1163 675 Shops breaking even count shops with [ profit = 0 ] 0 1 11 PLOT 8 610 273 760 Price variation Round Price variation 0.0 40.0 0.0 1.0 true false "" "" PENS "default" 1.0 0 -16777216 true "" "" PLOT 285 613 550 763 Profit and loss Round No. of shops 0.0 40.0 0.0 50.0 true true "" "" PENS "Loss" 1.0 0 -2674135 true "" "" "BE" 1.0 0 -16777216 true "" "" "Profit" 1.0 0 -13345367 true "" "" CHOOSER 159 10 329 55 scenario scenario "Perfect" "Real" 1 INPUTBOX 156 59 329 119 description test 1 0 String MONITOR 1060 696 1153 741 Shops in profit count shops with [ profit > 0 ] 17 1 11 MONITOR 641 718 775 763 NIL min [ wtp] of consumers 0 1 11 MONITOR 641 667 775 712 NIL max [ wtp ] of consumers 0 1 11 CHOOSER 9 242 176 287 search search "All" "About half" 0 MONITOR 186 240 386 285 initial mean no. of shops per consumer mean [ nOfSuppliers ] of consumers 1 1 11 CHOOSER 5 56 143 101 nOfShops nOfShops 1 2 10 20 50 100 2 MONITOR 810 688 1013 733 NIL count consumers with [ wtp > 10 ] 0 1 11 TEXTBOX 432 10 582 28 Based on unrestricted search 11 0.0 1 TEXTBOX 14 302 164 321 Additional variables 15 0.0 1 SLIDER 17 328 189 361 meanCapacityCost meanCapacityCost 0 10 2.5 0.5 1 NIL HORIZONTAL SLIDER 206 329 378 362 meanVariableCost meanVariableCost 0 10 7.5 0.5 1 NIL HORIZONTAL SLIDER 392 329 564 362 meanUtilisationRate% meanUtilisationRate% 0 100 100 1 1 NIL HORIZONTAL SLIDER 17 369 189 402 capacityIncrease% capacityIncrease% 0 100 10 1 1 NIL HORIZONTAL SLIDER 209 368 378 401 utilisationRateIncrease% utilisationRateIncrease% 0 100 10 1 1 NIL HORIZONTAL TEXTBOX 18 412 237 435 PLOTS FOR FIRST RUN 15 0.0 1 @#$#@#$#@ ## WHAT IS IT? Model of a simple market, based on small shops. ## HOW IT WORKS ### Consumers Number of consumers is fixed at 1,000. Each consumer is allocated a willingness-to-pay, lying between 5 and 15. Consumers buy once each round: ask consumers [ set ownDemand floor ( wtp / price ) ] Consumers seek out the cheapest shops within their range. ### Shops Mean capacity is determined by the number of shops / number of consumers to ensure that the market can clear. Mean capacity unit costs, mean varaible costs and mean utilisation rate are set by the modeller. Shops price on the basis of cost plus markup, so that if the shop operates at full capacity (i.e. utilisation = 100% ) it breaks even: markup x utilisation = cost per unit of capacity / variable cost See Box 6.3 for the underlying mathematics. Thus the coding is: set ownMarkUp precision ( ownCapacityCost / ownVariableCost ) 3 set ownPrice precision ( ownVariableCost * ( 1 + ownMarkUp ) ) 1 ### Scenarios There are two scenarios: ####Perfect All the shops are the same. set ownCapacity meanCapacity set ownCapacityCost meanCapacityCost set ownVariableCost meanVariableCost set ownUtilisationRate meanUtilisationRate% ####Real Shops' capacity, capacity costs, variable costs and utilisation rate is set at + or - 10% of the means. set ownCapacity precision ( random-normal meanCapacity ( meanCapacity * 0.1 ) ) 0 set ownCapacityCost precision ( random-normal meanCapacityCost ( meanCapacityCost * 0.1 ) ) 1 set ownVariableCost precision ( random-normal meanVariableCost ( meanVariableCost * 0.1 ) ) 1 set ownUtilisationRate precision ( random-normal meanUtilisationRate% ( meanUtilisationRate% * 0.1 ) / 100 ) 2 ### Adjustment process Every round - representing a quarter - shops change supply, price and variable costs according to sales - shops selling all their stock and operating below capacity, increase their their utilisation rate by 10% - shops not selling all their stock reduce their supply, prices (based on comparison with competitors) and costs - supply is reduced by half the difference between their capacity and their last sales set ownStock precision ( ownCapacity - ( ownCapacity - lastSales ) / 2 ) 2 - prices - if there are no competitors, prices are reduced by 10% - if there are competitors, the price is based on the average price of other shops within the distance set by the reach - the markup is set to 33% Every fourth round - to represent once a year - existing shops making a cumulative loss over the last 4 rounds die - existing shops making a profit over the last 4 rounds - and whose utilisation rate is less than 100%, increase their utilisation rate by 10% - and whose utilisation rate is 100%, increase their capacity by the 10% - The number of shops is kept constant. New shops are created using same capacity formula as original shops. ### Outputs Price, quantity and industry size are recorded at rounds 4, 8 20, 28 and 40 (i.e. at the end of year 1,2,5,7 and 10). For the first run, the results for all rounds is plotted. All the results, including the plots, are sent to a .csv file called "Shops-scenario-description". ## HOW TO USE IT Set the scenario. Set the number of shops and the search option. Set the number of rounds and runs required. If desired, set a description to help you identify the output file. WARNING: This model takes a long time to run. For example, 10 runs with 40 rounds can take 2 hours! ## THINGS TO TRY Experiment with the options offered by the sliders. For example: • what happens when the capacity costs are very low compared to the variable costs? (Change the meanCapapcity Costs and the meanVariableCosts) • what happens when capacity can be expanded quickly? (Change the capacity increase%) • what happens when the initial values are set far from the zero profit values? (Use the formulae in Box 6.3 to calculate the zer profit values.) Advanced: requiring programming: • change the set variables such as the mean and standard deviations of capacity, capacity and variable costs and utilisation rate. • change the adjustment process. o change the utilisationRateIncrease% or the capacityIncrease% o make more sophisticated changes • use this program as the basis for other models of markets ## CREDITS AND REFERENCES Runs on NetLogo 5.2. For more information, see Hamill, L. & Gilbert, N. (2016) Agent-based Modelling in Economics. Wiley: Chapter 6. To refer to this model: Hamill, L. & Gilbert, N. (2016) Shops model. @#$#@#$#@ default true 0 Polygon -7500403 true true 150 5 40 250 150 205 260 250 airplane true 0 Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15 arrow true 0 Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150 box false 0 Polygon -7500403 true true 150 285 285 225 285 75 150 135 Polygon -7500403 true true 150 135 15 75 150 15 285 75 Polygon -7500403 true true 15 75 15 225 150 285 150 135 Line -16777216 false 150 285 150 135 Line -16777216 false 150 135 15 75 Line -16777216 false 150 135 285 75 bug true 0 Circle -7500403 true true 96 182 108 Circle -7500403 true true 110 127 80 Circle -7500403 true true 110 75 80 Line -7500403 true 150 100 80 30 Line -7500403 true 150 100 220 30 butterfly true 0 Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240 Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240 Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163 Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165 Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225 Circle -16777216 true false 135 90 30 Line -16777216 false 150 105 195 60 Line -16777216 false 150 105 105 60 car false 0 Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180 Circle -16777216 true false 180 180 90 Circle -16777216 true false 30 180 90 Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89 Circle -7500403 true true 47 195 58 Circle -7500403 true true 195 195 58 circle false 0 Circle -7500403 true true 0 0 300 circle 2 false 0 Circle -7500403 true true 0 0 300 Circle -16777216 true false 30 30 240 cow false 0 Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167 Polygon -7500403 true true 73 210 86 251 62 249 48 208 Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123 cylinder false 0 Circle -7500403 true true 0 0 300 dot false 0 Circle -7500403 true true 90 90 120 face happy false 0 Circle -7500403 true true 8 8 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240 face neutral false 0 Circle -7500403 true true 8 7 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Rectangle -16777216 true false 60 195 240 225 face sad false 0 Circle -7500403 true true 8 8 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183 fish false 0 Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166 Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165 Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60 Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166 Circle -16777216 true false 215 106 30 flag false 0 Rectangle -7500403 true true 60 15 75 300 Polygon -7500403 true true 90 150 270 90 90 30 Line -7500403 true 75 135 90 135 Line -7500403 true 75 45 90 45 flower false 0 Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135 Circle -7500403 true true 85 132 38 Circle -7500403 true true 130 147 38 Circle -7500403 true true 192 85 38 Circle -7500403 true true 85 40 38 Circle -7500403 true true 177 40 38 Circle -7500403 true true 177 132 38 Circle -7500403 true true 70 85 38 Circle -7500403 true true 130 25 38 Circle -7500403 true true 96 51 108 Circle -16777216 true false 113 68 74 Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218 Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240 house false 0 Rectangle -7500403 true true 45 120 255 285 Rectangle -16777216 true false 120 210 180 285 Polygon -7500403 true true 15 120 150 15 285 120 Line -16777216 false 30 120 270 120 leaf false 0 Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195 Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195 line true 0 Line -7500403 true 150 0 150 300 line half true 0 Line -7500403 true 150 0 150 150 pentagon false 0 Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120 person false 0 Circle -7500403 true true 110 5 80 Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90 Rectangle -7500403 true true 127 79 172 94 Polygon -7500403 true true 195 90 240 150 225 180 165 105 Polygon -7500403 true true 105 90 60 150 75 180 135 105 plant false 0 Rectangle -7500403 true true 135 90 165 300 Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285 Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285 Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210 Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135 Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135 Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60 Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90 sheep false 0 Rectangle -7500403 true true 151 225 180 285 Rectangle -7500403 true true 47 225 75 285 Rectangle -7500403 true true 15 75 210 225 Circle -7500403 true true 135 75 150 Circle -16777216 true false 165 76 116 square false 0 Rectangle -7500403 true true 30 30 270 270 square 2 false 0 Rectangle -7500403 true true 30 30 270 270 Rectangle -16777216 true false 60 60 240 240 star false 0 Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108 target false 0 Circle -7500403 true true 0 0 300 Circle -16777216 true false 30 30 240 Circle -7500403 true true 60 60 180 Circle -16777216 true false 90 90 120 Circle -7500403 true true 120 120 60 tree false 0 Circle -7500403 true true 118 3 94 Rectangle -6459832 true false 120 195 180 300 Circle -7500403 true true 65 21 108 Circle -7500403 true true 116 41 127 Circle -7500403 true true 45 90 120 Circle -7500403 true true 104 74 152 triangle false 0 Polygon -7500403 true true 150 30 15 255 285 255 triangle 2 false 0 Polygon -7500403 true true 150 30 15 255 285 255 Polygon -16777216 true false 151 99 225 223 75 224 truck false 0 Rectangle -7500403 true true 4 45 195 187 Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194 Rectangle -1 true false 195 60 195 105 Polygon -16777216 true false 238 112 252 141 219 141 218 112 Circle -16777216 true false 234 174 42 Rectangle -7500403 true true 181 185 214 194 Circle -16777216 true false 144 174 42 Circle -16777216 true false 24 174 42 Circle -7500403 false true 24 174 42 Circle -7500403 false true 144 174 42 Circle -7500403 false true 234 174 42 turtle true 0 Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210 Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105 Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105 Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87 Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210 Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99 wheel false 0 Circle -7500403 true true 3 3 294 Circle -16777216 true false 30 30 240 Line -7500403 true 150 285 150 15 Line -7500403 true 15 150 285 150 Circle -7500403 true true 120 120 60 Line -7500403 true 216 40 79 269 Line -7500403 true 40 84 269 221 Line -7500403 true 40 216 269 79 Line -7500403 true 84 40 221 269 x false 0 Polygon -7500403 true true 270 75 225 30 30 225 75 270 Polygon -7500403 true true 30 75 75 30 270 225 225 270 @#$#@#$#@ NetLogo 5.2.0 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ default 0.0 -0.2 0 0.0 1.0 0.0 1 1.0 0.0 0.2 0 0.0 1.0 link direction true 0 Line -7500403 true 150 150 90 180 Line -7500403 true 150 150 210 180 @#$#@#$#@ 0 @#$#@#$#@