instances
Module¶
Overview¶
The instances
module contains code for loading and saving problem instances.
Note
The notation and references (equations, sections, examples, etc.) used below refer to Snyder and Shen, Fundamentals of Supply Chain Theory (FoSCT), 2nd edition (2019).
The abbreviation SCMO below refers to the textbook Supply Chain Modeling and Optimization by Snyder, Smilowitz, and Shen, forthcoming.
Stockpyl has a number of built-in instances, most (but not all) of which are taken from FoSCT.
These can be loaded using the load_instance()
function by providing the instance name.
A list of the built-in instances is provided below.
Deterministic Single-Echelon Inventory Problems
Example 3.1 (EOQ)
example_3_1
instance = load_instance('example_3_1')
instance = {
'fixed_cost': 8,
'holding_cost': 0.225,
'demand_rate': 1300
}
Problem 3.1 (EOQ)
problem_3_1
instance = load_instance('problem_3_1')
instance = {
'fixed_cost': 2250,
'holding_cost': 275,
'demand_rate': 182500
}
Example 3.8 (EOQB)
example_3_8
instance = load_instance('example_3_8')
instance = {
'fixed_cost': 8,
'holding_cost': 0.225,
'stockout_cost': 5,
'demand_rate': 1300
}
Problem 3.2(b) (EOQB)
problem_3_2b
instance = load_instance('problem_3_2b')
instance = {
'fixed_cost': 40,
'holding_cost': 40.05,
'stockout_cost': 60,
'demand_rate': 2080
}
Problem 3.22 (EPQ)
problem_3_22
instance = load_instance('problem_3_22')
instance = {
'fixed_cost': 4,
'holding_cost': 0.08,
'demand_rate': 80,
'production_rate': 110
}
Example 3.9 (Wagner-Whitin)
example_3_9
instance = load_instance('example_3_9')
instance = {
"num_periods": 4,
"holding_cost": 2,
"fixed_cost": 500,
"demand": [
90,
120,
80,
70
]
}
Problem 3.27 (Wagner-Whitin)
problem_3_27
instance = load_instance('problem_3_27')
instance = {
"num_periods": 4,
"holding_cost": 0.8,
"fixed_cost": 120,
"demand": [
150,
100,
80,
200
]
}
Problem 3.29 (Wagner-Whitin)
problem_3_29
instance = load_instance('problem_3_29')
instance = {
"num_periods": 5,
"holding_cost": 0.1,
"fixed_cost": 100,
"demand": [
730,
580,
445,
650,
880
]
}
SCMO (Wagner-Whitin with nonstationary purchase cost)
scmo_ww_hw_c
instance = load_instance('scmo_ww_hw_c')
instance = {
"num_periods": 5,
"holding_cost": 0.1,
"fixed_cost": 100,
"demand": [
400,
500,
500,
1100,
900
],
"purchase_cost": [
3,
1,
4,
6,
6
]
}
SCMO (JRP example)
scmo_jrp_ex
instance = load_instance('scmo_jrp_ex')
instance = {
"shared_fixed_cost": 600,
"individual_fixed_costs": [
120,
840,
300
],
"holding_costs": [
160,
20,
50
],
"demand_rates": [
1,
1,
1
]
}
Numerical JRP example on p. 428 of Silver, Pyke, and Peterson (1998)
spp_jrp
instance = load_instance('spp_jrp')
instance = {
"shared_fixed_cost": 40,
"individual_fixed_costs": [
15,
15,
15,
15
],
"holding_costs": [
0.24,
0.24,
0.24,
0.24
],
"demand_rates": [
86000,
12500,
1400,
3000
]
}
Numerical JRP example in Silver (1976)
silver_jrp
instance = load_instance('silver_jrp')
instance = {
"shared_fixed_cost": 10,
"individual_fixed_costs": [
1.87,
5.27,
7.94,
8.19,
8.87
],
"holding_costs": [
0.2,
0.2,
0.2,
0.2,
0.2
],
"demand_rates": [
1736,
656,
558,
170,
142
]
}
SCMO (JRP problem 1)
scmo_jrp_hw_1
instance = load_instance('scmo_jrp_hw_1')
instance = {
"shared_fixed_cost": 20000,
"individual_fixed_costs": [
36000,
46000,
34000,
38000
],
"holding_costs": [
1000,
900,
1200,
1000
],
"demand_rates": [
1780,
445,
920,
175
]
}
SCMO (JRP problem 2)
scmo_jrp_hw_2
instance = load_instance('scmo_jrp_hw_2')
instance = {
"shared_fixed_cost": 1500,
"individual_fixed_costs": [
4000,
1000,
2000
],
"holding_costs": [
300,
200,
200
],
"demand_rates": [
9100,
83200,
20800
]
}
SCMO (JRP problem 3)
scmo_jrp_hw_3
instance = load_instance('scmo_jrp_hw_3')
instance = {
"shared_fixed_cost": 180,
"individual_fixed_costs": [
60,
100,
180,
115,
135
],
"holding_costs": [
5.32,
3.9200000000000004,
4.760000000000001,
3.9200000000000004,
3.3600000000000003
],
"demand_rates": [
6200,
1300,
400,
4400,
1800
]
}
Stochastic Single-Echelon Inventory Problems
Example 4.1 (newsvendor)
example_4_1
instance = load_instance('example_4_1')
instance = {
"holding_cost": 0.18,
"stockout_cost": 0.7,
"demand_mean": 50,
"demand_sd": 8
}
Example 4.1 (newsvendor) (as SupplyChainNetwork object)
example_4_1_network
instance = load_instance('example_4_1_network')
from stockpyl.supply_chain_network import single_stage_system
instance = single_stage_system(
holding_cost=0.18,
stockout_cost=0.7,
demand_type='N',
mean=50,
standard_deviation=8,
shipment_lead_time=1,
policy_type='BS',
base_stock_level=56.6
)
Example 4.2 (newsvendor explicit)
example_4_2
instance = load_instance('example_4_2')
instance = {
"revenue": 1,
"purchase_cost": 0.3,
"salvage_value": 0.12,
"demand_mean": 50,
"demand_sd": 8
}
Example 4.3 (newsvendor) (= Example 4.1)
example_4_3
instance = load_instance('example_4_3')
instance = {
"holding_cost": 0.18,
"stockout_cost": 0.7,
"demand_mean": 50,
"demand_sd": 8
}
Problem 4.1 (newsvendor)
problem_4_1
instance = load_instance('problem_4_1')
instance = {
"holding_cost": 43,
"stockout_cost": 79,
"demand_mean": 900,
"demand_sd": 60
}
Problem 4.3(b) (newsvendor explicit)
problem_4_3b
instance = load_instance('problem_4_3b')
instance = {
"revenue": 7,
"purchase_cost": 2.5,
"salvage_value": 1.5,
"demand_mean": 50,
"demand_sd": 10
}
Example 4.4 (base-stock optimization)
example_4_4
instance = load_instance('example_4_4')
instance = {
"holding_cost": 0.18,
"stockout_cost": 0.7,
"demand_mean": 50,
"demand_sd": 8,
"lead_time": 4
}
Example 4.7 ((s,S) with Poisson demand)
example_4_7
instance = load_instance('example_4_7')
instance = {
"holding_cost": 1,
"stockout_cost": 4,
"fixed_cost": 5,
"demand_mean": 6
}
Problem 4.7(b) (newsvendor with discrete demand)
problem_4_7b
instance = load_instance('problem_4_7b')
instance = {
"holding_cost": 500000,
"stockout_cost": 1000000,
"demand_pmf": {
"1": 0.25,
"2": 0.05,
"3": 0.1,
"4": 0.2,
"5": 0.15,
"6": 0.1,
"7": 0.1,
"8": 0.05
}
}
Problem 4.8(a) (newsvendor with Poisson demand)
problem_4_8a
instance = load_instance('problem_4_8a')
instance = {
"holding_cost": 200,
"stockout_cost": 270,
"demand_mean": 18
}
Problem 4.8(b) (newsvendor with lognormal demand)
problem_4_8b
instance = load_instance('problem_4_8b')
instance = {
"holding_cost": 1,
"stockout_cost": 0.1765,
"mu": 6,
"sigma": 0.3
}
Problem 4.31 ((s,S) with Poisson demand)
problem_4_31
instance = load_instance('problem_4_31')
instance = {
"holding_cost": 40,
"stockout_cost": 125,
"fixed_cost": 150,
"demand_mean": 4
}
Example 4.8 ((s,S))
example_4_8
instance = load_instance('example_4_8')
instance = {
"holding_cost": 0.18,
"stockout_cost": 0.7,
"fixed_cost": 2.5,
"demand_mean": 50,
"demand_sd": 8
}
Problem 4.32 ((s,S))
problem_4_32
instance = load_instance('problem_4_32')
instance = {
"holding_cost": 2,
"stockout_cost": 36,
"fixed_cost": 60,
"demand_mean": 190,
"demand_sd": 48
}
Problem 4.29 (finite-horizon)
problem_4_29
instance = load_instance('problem_4_29')
instance = {
"num_periods": 10,
"holding_cost": 1,
"stockout_cost": 25,
"terminal_holding_cost": 1,
"terminal_stockout_cost": 25,
"purchase_cost": 1,
"fixed_cost": 0,
"demand_mean": 18,
"demand_sd": 3,
"discount_factor": 0.98,
"initial_inventory_level": 0
}
Problem 4.30 (finite-horizon)
problem_4_30
instance = load_instance('problem_4_30')
instance = {
"num_periods": 10,
"holding_cost": 1,
"stockout_cost": 25,
"terminal_holding_cost": 1,
"terminal_stockout_cost": 25,
"purchase_cost": 1,
"fixed_cost": 40,
"demand_mean": 18,
"demand_sd": 3,
"discount_factor": 0.98,
"initial_inventory_level": 0
}
Example 5.1 ((r,Q))
example_5_1
instance = load_instance('example_5_1')
instance = {
"holding_cost": 0.225,
"stockout_cost": 7.5,
"fixed_cost": 8,
"demand_mean": 1300,
"demand_sd": 150,
"lead_time": 0.08333333333333333
}
Problem 5.1 ((r,Q))
problem_5_1
instance = load_instance('problem_5_1')
instance = {
"holding_cost": 3.1,
"stockout_cost": 45,
"fixed_cost": 50,
"demand_mean": 800,
"demand_sd": 40,
"lead_time": 0.010958904109589041
}
Problem 5.2 ((r,Q) with Poisson demand)
problem_5_2
instance = load_instance('problem_5_2')
instance = {
"holding_cost": 4,
"stockout_cost": 28,
"fixed_cost": 4,
"demand_mean": 12,
"lead_time": 0.5
}
Problem 5.3 ((r,Q))
problem_5_3
instance = load_instance('problem_5_3')
instance = {
"holding_cost": 0.21428571428571427,
"stockout_cost": 40,
"fixed_cost": 85,
"demand_mean": 192,
"demand_sd": 17.4,
"lead_time": 3
}
Example 5.8 ((r,Q) with Poisson demand))
example_5_8
instance = load_instance('example_5_8')
instance = {
"holding_cost": 20,
"stockout_cost": 150,
"fixed_cost": 100,
"demand_mean": 1.5,
"lead_time": 2
}
Stochastic Multi-Echelon Inventory Problems
Example 6.1 (serial SSM)
example_6_1
instance = load_instance('example_6_1')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=3,
node_order_in_system=[3, 2, 1],
echelon_holding_cost={1: 3, 2: 2, 3: 2},
local_holding_cost={1: 7, 2: 4, 3: 2},
shipment_lead_time={1: 1, 2: 1, 3: 2},
stockout_cost={1: 37.12, 2: 0, 3: 0},
demand_type='N',
mean=5,
standard_deviation=1,
policy_type='BS',
base_stock_level={1: 6.49, 2: 5.53, 3: 10.69}
)
Problem 6.1 (serial SSM)
problem_6_1
instance = load_instance('problem_6_1')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=2,
node_order_in_system=[2, 1],
node_order_in_lists=[1, 2],
local_holding_cost=[2, 1],
echelon_holding_cost=[1, 1],
stockout_cost=[15, 0],
demand_type='N',
mean=100,
standard_deviation=15,
shipment_lead_time=[1, 1],
policy_type='BS',
base_stock_level=[100, 94]
)
Problem 6.2(a) (serial SSM)
problem_6_2a
instance = load_instance('problem_6_2a')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=5,
node_order_in_system=[5, 4, 3, 2, 1],
node_order_in_lists=[1, 2, 3, 4, 5],
local_holding_cost=[1, 2, 3, 5, 7],
echelon_holding_cost=[2, 2, 1, 1, 1],
stockout_cost=[24, 0, 0, 0, 0],
demand_type='N',
mean=64,
standard_deviation=8,
shipment_lead_time=[0.5, 0.5, 0.5, 0.5, 0.5],
policy_type='BS',
base_stock_level=[40.59, 33.87, 35.14, 33.30, 32.93]
)
Problem 6.2(a) (serial SSM with Poisson demand)
problem_6_2b
instance = load_instance('problem_6_2b')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=5,
node_order_in_system=[5, 4, 3, 2, 1],
node_order_in_lists=[1, 2, 3, 4, 5],
local_holding_cost=[1, 2, 3, 5, 7],
echelon_holding_cost=[2, 2, 1, 1, 1],
stockout_cost=[24, 0, 0, 0, 0],
demand_type='P',
mean=64,
shipment_lead_time=[0.5, 0.5, 0.5, 0.5, 0.5],
policy_type='BS',
base_stock_level=[40.59, 33.87, 35.14, 33.30, 32.93]
)
Problem 6.2(a) (serial SSM), adjusted for periodic review
problem_6_2a_adj
instance = load_instance('problem_6_2a_adj')
from stockpyl.supply_chain_network import serial_system
import numpy as np
instance = serial_system(
num_nodes=5,
node_order_in_system=[5, 4, 3, 2, 1],
node_order_in_lists=[1, 2, 3, 4, 5],
local_holding_cost=list(np.array([1, 2, 3, 5, 7]) / 2),
stockout_cost=list(np.array([24, 0, 0, 0, 0]) / 2),
demand_type='N',
mean=64 / 2,
standard_deviation=8 / np.sqrt(2),
shipment_lead_time=[1, 1, 1, 1, 1],
policy_type='BS',
base_stock_level=[40.59, 33.87, 35.14, 33.30, 32.93]
)
Problem 6.2(b) (serial SSM with Poisson demand), adjusted for periodic review
problem_6_2b_adj
instance = load_instance('problem_6_2b_adj')
from stockpyl.supply_chain_network import serial_system
import numpy as np
instance = serial_system(
num_nodes=5,
node_order_in_system=[5, 4, 3, 2, 1],
node_order_in_lists=[1, 2, 3, 4, 5],
local_holding_cost=list(np.array([1, 2, 3, 5, 7]) / 2),
stockout_cost=list(np.array([24, 0, 0, 0, 0]) / 2),
demand_type='P',
mean=64 / 2,
shipment_lead_time=[1, 1, 1, 1, 1],
policy_type='BS',
base_stock_level=[40.59, 33.87, 35.14, 33.30, 32.93]
)
Problem 6.16 (serial SSM)
problem_6_16
instance = load_instance('problem_6_16')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=2,
node_order_in_system=[2, 1],
node_order_in_lists=[1, 2],
local_holding_cost=[7, 2],
echelon_holding_cost=[5, 2],
stockout_cost=[24, 0],
demand_type='N',
mean=20,
standard_deviation=4,
shipment_lead_time=[8, 3],
policy_type='BS',
base_stock_level=[171.1912, 57.7257],
initial_inventory_level=20,
initial_orders=20,
initial_shipments=20
)
Serial SSM system in Shang and Song (2003), Table 1, row 1
shang_song_1
instance = load_instance('shang_song_1')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=4,
node_order_in_system=[4, 3, 2, 1],
echelon_holding_cost=0.25,
shipment_lead_time=0.25,
stockout_cost={1: 9},
demand_type='P',
mean=16,
policy_type='BS'
)
Serial SSM system in Shang and Song (2003), Table 1, row 9
shang_song_9
instance = load_instance('shang_song_9')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=4,
node_order_in_system=[4, 3, 2, 1],
node_order_in_lists=[1, 2, 3, 4],
echelon_holding_cost=[0.25, 2.5, 2.5, 0.25],
shipment_lead_time=0.25,
stockout_cost={1: 9},
demand_type='P',
mean=16,
policy_type='BS'
)
Serial SSM system in Shang and Song (2003), Table 1, row 17
shang_song_17
instance = load_instance('shang_song_17')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=4,
node_order_in_system=[4, 3, 2, 1],
echelon_holding_cost=0.25,
shipment_lead_time=0.25,
stockout_cost={1: 99},
demand_type='P',
mean=16,
policy_type='BS'
)
Serial SSM system in Shang and Song (2003), Table 1, row 25
shang_song_25
instance = load_instance('shang_song_25')
from stockpyl.supply_chain_network import serial_system
instance = serial_system(
num_nodes=4,
node_order_in_system=[4, 3, 2, 1],
node_order_in_lists=[1, 2, 3, 4],
echelon_holding_cost=[0.25, 2.5, 2.5, 0.25],
shipment_lead_time=0.25,
stockout_cost={1: 99},
demand_type='P',
mean=16,
policy_type='BS'
)
3-stage assembly system (2 warehouses, 1 retailer)
assembly_3_stage
instance = load_instance('assembly_3_stage')
from stockpyl.supply_chain_network import mwor_system
instance = mwor_system(
num_warehouses=2,
node_order_in_lists=[0, 1, 2],
local_holding_cost=[2, 1, 1],
stockout_cost=[20, 0, 0],
demand_type='N',
mean=5,
standard_deviation=1,
shipment_lead_time=[1, 2, 2],
policy_type='BS',
base_stock_level=[7, 13, 11],
initial_inventory_level=[7, 13, 11]
)
instance.get_node_from_index(0).demand_source.round_to_int = True
Assembly system from Figure 1 in Rosling (1989)
rosling_figure_1
instance = load_instance('rosling_figure_1')
from stockpyl.supply_chain_network import SupplyChainNetwork
from stockpyl.supply_chain_node import SupplyChainNode
from stockpyl.demand_source import DemandSource
instance = SupplyChainNetwork()
nodes = {i: SupplyChainNode(index=i) for i in range(1, 8)}
# Inventory policies (balanced echelon base-stock).
for n in nodes.values():
n.inventory_policy.type = 'BEBS'
n.inventory_policy.base_stock_level = None
# Node 1.
nodes[1].shipment_lead_time = 1
nodes[1].demand_source = DemandSource(type='UD', lo=0, hi=10)
nodes[1].supply_type = None
nodes[1].inventory_policy.base_stock_level = 8
nodes[1].initial_inventory_level = 8
instance.add_node(nodes[1])
# Node 2.
nodes[2].shipment_lead_time = 1
nodes[2].supply_type = None
nodes[2].inventory_policy.base_stock_level = 24
nodes[2].initial_inventory_level = 8
instance.add_predecessor(nodes[1], nodes[2])
# Node 3.
nodes[3].shipment_lead_time = 3
nodes[3].supply_type = None
nodes[3].inventory_policy.base_stock_level = 40
nodes[3].initial_inventory_level = 24
instance.add_predecessor(nodes[1], nodes[3])
# Node 4.
nodes[4].shipment_lead_time = 2
nodes[4].supply_type = None
nodes[4].inventory_policy.base_stock_level = 76
nodes[4].initial_inventory_level = 16
instance.add_predecessor(nodes[3], nodes[4])
# Node 5.
nodes[5].shipment_lead_time = 4
nodes[5].inventory_policy.base_stock_level = 62
nodes[5].initial_inventory_level = 32
nodes[5].supply_type = 'U'
instance.add_predecessor(nodes[2], nodes[5])
# Node 6.
nodes[6].shipment_lead_time = 1
nodes[6].supply_type = 'U'
nodes[6].inventory_policy.base_stock_level = 84
nodes[6].initial_inventory_level = 8
instance.add_predecessor(nodes[4], nodes[6])
# Node 7.
nodes[7].shipment_lead_time = 2
nodes[7].supply_type = 'U'
nodes[7].inventory_policy.base_stock_level = 92
nodes[7].initial_inventory_level = 16
instance.add_predecessor(nodes[4], nodes[7])
Distribution system from Figure 1(a) in Rong, Atan, and Snyder (2017)
rong_atan_snyder_figure_1a
instance = load_instance('rong_atan_snyder_figure_1a')
from stockpyl.supply_chain_network import network_from_edges
from math import sqrt
instance = network_from_edges(
edges=[(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), (2, 6)],
demand_type={0: None, 1: None, 2: None, 3: 'N', 4: 'N', 5: 'N', 6: 'N'},
mean=8,
standard_deviation=sqrt(8),
local_holding_cost={0: 1/3, 1: 2/3, 2: 2/3, 3: 1, 4: 1, 5: 1, 6: 1},
stockout_cost=20,
shipment_lead_time=1,
policy_type='BS',
base_stock_level={i: 0 for i in range(0, 7)}
)
Distribution system from Figure 1(b) in Rong, Atan, and Snyder (2017)
rong_atan_snyder_figure_1b
instance = load_instance('rong_atan_snyder_figure_1b')
from stockpyl.supply_chain_network import network_from_edges
from math import sqrt
demand_type = {i: 'N' if i >= 3 else None for i in range(11)}
instance = network_from_edges(
edges=[(0, 1), (0, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (2, 8), (2, 9), (2, 10)],
demand_type=demand_type,
mean=8,
standard_deviation=sqrt(8),
policy_type='BS',
base_stock_level={i: 0 for i in range(0, 11)}
)
Distribution system from Figure 1(c) in Rong, Atan, and Snyder (2017)
rong_atan_snyder_figure_1c
instance = load_instance('rong_atan_snyder_figure_1c')
from stockpyl.supply_chain_network import network_from_edges
from math import sqrt
instance = network_from_edges(
edges=[(0, 1), (0, 2), (2, 3), (2, 4), (2, 5)],
demand_type={0: None, 1: 'N', 2: None, 3: 'N', 4: 'N', 5: 'N'},
mean=8,
standard_deviation=sqrt(8),
policy_type='BS',
base_stock_level={i: 0 for i in range(0, 6)}
)
Example 6.3 (serial GSM)
example_6_3
instance = load_instance('example_6_3')
from stockpyl.supply_chain_network import network_from_edges
instance = network_from_edges(
edges=[(3, 2), (2, 1)],
node_order_in_lists=[1, 2, 3],
processing_time=[1, 0, 1],
external_inbound_cst=[None, None, 1],
local_holding_cost=[7, 4, 2],
demand_bound_constant=1,
external_outbound_cst=[1, None, None],
demand_type=['N', None, None],
mean=0,
standard_deviation=[1, 0, 0]
)
Problem 6.7 (serial GSM)
problem_6_7
instance = load_instance('problem_6_7')
from stockpyl.supply_chain_network import SupplyChainNetwork
from stockpyl.supply_chain_node import SupplyChainNode
from stockpyl.demand_source import DemandSource
instance = SupplyChainNetwork()
instance.add_node(SupplyChainNode(3, name='Forming', network=instance, processing_time=1, local_holding_cost=2, external_inbound_cst=1, demand_bound_constant=4))
instance.add_node(SupplyChainNode(2, name='Firing', network=instance, processing_time=1, local_holding_cost=3, demand_bound_constant=4))
instance.add_node(SupplyChainNode(1, name='Glazing', network=instance, processing_time=2, local_holding_cost=4, external_outbound_cst=0, demand_source=DemandSource(type='N', mean=45, standard_deviation=10), demand_bound_constant=4))
instance.add_edges_from_list([(3, 2), (2, 1)])
Problem 6.8 (serial GSM)
problem_6_8
instance = load_instance('problem_6_8')
from stockpyl.supply_chain_network import network_from_edges
from scipy import stats
instance = network_from_edges(
[(n+1, n) for n in range(1, 10)],
node_order_in_lists=list(range(1, 11)),
processing_time=[5, 10, 2, 15, 8, 5, 9, 5, 1, 5],
external_inbound_cst=[None] * 9 + [7],
local_holding_cost=[5.73, 4.56, 3.04, 2.93, 2.47, 2.37, 1.15, 1.1, 0.98, 0.87],
demand_bound_constant=stats.norm.ppf(0.98),
external_outbound_cst=[3] + [None] * 9,
demand_type=['N'] + [None] * 9,
mean=0,
standard_deviation=[15.8] + [None] * 9
)
Problem 6.9 (tree GSM)
problem_6_9
instance = load_instance('problem_6_9')
from stockpyl.supply_chain_network import SupplyChainNetwork
from stockpyl.supply_chain_node import SupplyChainNode
from stockpyl.demand_source import DemandSource
instance = SupplyChainNetwork()
instance.add_node(SupplyChainNode(1, network=instance, processing_time=7, local_holding_cost=220*0.2/365, external_outbound_cst=3, demand_source=DemandSource(type='N', mean=22.0, standard_deviation=4.1), demand_bound_constant=4))
instance.add_node(SupplyChainNode(2, network=instance, processing_time=7, local_holding_cost=140*0.2/365, external_outbound_cst=3, demand_source=DemandSource(type='N', mean=15.3, standard_deviation=6.2), demand_bound_constant=4))
instance.add_node(SupplyChainNode(3, network=instance, processing_time=21, local_holding_cost=90*0.2/365, demand_bound_constant=4))
instance.add_node(SupplyChainNode(4, network=instance, processing_time=3, local_holding_cost=5*0.2/365, demand_bound_constant=4))
instance.add_node(SupplyChainNode(5, network=instance, processing_time=8, local_holding_cost=20*0.2/365, demand_bound_constant=4))
instance.add_node(SupplyChainNode(6, network=instance, processing_time=2, local_holding_cost=7.5*0.2/365, demand_bound_constant=4))
instance.add_edges_from_list([(6, 5), (4, 3), (5, 3), (3, 1), (3, 2)])
Example 6.5 (tree GSM)
example_6_5
instance = load_instance('example_6_5')
from stockpyl.supply_chain_network import network_from_edges
instance = network_from_edges(
edges=[(1, 3), (3, 2), (3, 4)],
node_order_in_lists=[1, 2, 3, 4],
processing_time=[2, 1, 1, 1],
external_inbound_cst=[1, None, None, None],
local_holding_cost=[1, 3, 2, 3],
demand_bound_constant=[1, 1, 1, 1],
external_outbound_cst=[None, 0, None, 1],
demand_type=[None, 'N', None, 'N'],
mean=[None, 0, None, 0],
standard_deviation=[None, 1, None, 1]
)
Figure 6.12 (tree GSM)
figure_6_12
instance = load_instance('figure_6_12')
from stockpyl.supply_chain_network import network_from_edges
instance = network_from_edges(
edges=[(1, 2), (1, 3), (3, 5), (4, 5), (5, 6), (5, 7)]
)
Figure 6.14 (tree GSM)
figure_6_14
instance = load_instance('figure_6_14')
from stockpyl.supply_chain_network import SupplyChainNetwork
from stockpyl.supply_chain_node import SupplyChainNode
from stockpyl.demand_source import DemandSource
from scipy import stats
instance = SupplyChainNetwork()
instance.add_node(SupplyChainNode(1, 'Raw_Material', instance, processing_time=2, local_holding_cost=0.01))
instance.add_node(SupplyChainNode(2, 'Process_Wafers', instance, processing_time=3, local_holding_cost=0.03))
instance.add_node(SupplyChainNode(3, 'Package_Test_Wafers', instance, processing_time=2, local_holding_cost=0.04))
instance.add_node(SupplyChainNode(4, 'Imager_Base', instance, processing_time=4, local_holding_cost=0.06))
instance.add_node(SupplyChainNode(5, 'Imager_Assembly', instance, processing_time=2, local_holding_cost=0.12))
instance.add_node(SupplyChainNode(6, 'Ship_to_Final_Assembly', instance, processing_time=3, local_holding_cost=0.13))
instance.add_node(SupplyChainNode(7, 'Camera', instance, processing_time=6, local_holding_cost=0.20))
instance.add_node(SupplyChainNode(8, 'Circuit_Board', instance, processing_time=4, local_holding_cost=0.08))
instance.add_node(SupplyChainNode(9, 'Other_Parts', instance, processing_time=3, local_holding_cost=0.04))
instance.add_node(SupplyChainNode(10, 'Build_Test_Pack', instance, processing_time=2, local_holding_cost=0.50, \
external_outbound_cst=2, demand_source=DemandSource(type='N', mean=0, standard_deviation=10)))
for n in instance.nodes:
n.demand_bound_constant = stats.norm.ppf(0.95)
instance.add_edges_from_list([(1, 2), (2, 3), (3, 5), (4, 5), (5, 6), (7, 10), (6, 10), (8, 10), (9, 10)])
Single-Echelon Inventory Problems with Supply Uncertainty
Example 9.1 (EOQD)
example_9_1
instance = load_instance('example_9_1')
instance = {
"holding_cost": 0.225,
"stockout_cost": 5,
"fixed_cost": 8,
"demand_rate": 1300,
"disruption_rate": 1.5,
"recovery_rate": 14
}
Problem 9.8 (EOQD)
problem_9_8
instance = load_instance('problem_9_8')
instance = {
"holding_cost": 4,
"stockout_cost": 22,
"fixed_cost": 35,
"demand_rate": 30,
"disruption_rate": 1,
"recovery_rate": 12
}
Example 9.3 (base-stock with disruptions)
example_9_3
instance = load_instance('example_9_3')
instance = {
"holding_cost": 0.25,
"stockout_cost": 3,
"demand": 2000,
"disruption_prob": 0.04,
"recovery_prob": 0.25
}
Example 9.4 (EOQ with additive yield uncertainty)
example_9_4
instance = load_instance('example_9_4')
instance = {
"holding_cost": 0.06,
"fixed_cost": 18500,
"demand_rate": 75000,
"yield_mean": -15000,
"yield_sd": 9000
}
Example 9.5 (EOQ with multiplicative yield uncertainty)
example_9_5
instance = load_instance('example_9_5')
instance = {
"holding_cost": 0.06,
"fixed_cost": 18500,
"demand_rate": 75000,
"yield_mean": 0.8333333333333334,
"yield_sd": 0.14085904245475275
}
Problem 9.4(a) (EOQ with additive yield uncertainty)
problem_9_4a
instance = load_instance('problem_9_4a')
instance = {
"holding_cost": 275,
"fixed_cost": 2250,
"demand_rate": 182500,
"yield_mean": -50.0,
"yield_sd": 0.02
}
Problem 9.4(b) (EOQ with multiplicative yield uncertainty)
problem_9_4b
instance = load_instance('problem_9_4b')
instance = {
"holding_cost": 275,
"fixed_cost": 2250,
"demand_rate": 182500,
"yield_mean": 0.9,
"yield_sd": 0.05773502691896258
}
Example 9.6 (newsvendor with additive yield uncertainty)
example_9_6
instance = load_instance('example_9_6')
instance = {
"holding_cost": 15000000,
"stockout_cost": 75000000,
"demand": 1.5,
"yield_lo": -0.5,
"yield_hi": 0.5
}
Problem 9.5 (newsvendor with additive yield uncertainty)
problem_9_5
instance = load_instance('problem_9_5')
instance = {
"holding_cost": 150,
"stockout_cost": 1200,
"demand": 25,
"yield_lo": -5,
"yield_hi": 0
}
API Reference¶
- load_instance(instance_name, filepath=None, ignore_state_vars=True)[source]¶
Load an instance from a JSON file.
If the instance was originally specified as a
SupplyChainNetwork
object, returns the object; otherwise, returns the instance in a dictionary.- Parameters
instance_name (str) – The name of the instance.
filepath (str, optional) – Path to the JSON file. If
None
, the function determines the path todatasets/stockpyl_instances.json
.ignore_state_vars (bool, optional) – If
True
, function will ignore any saved state variables in the nodes.
- Returns
The loaded instance. If the instance was originally specified as a
SupplyChainNetwork
object, returns the object; otherwise, returns the instance in a dictionary in which the keys equal the parameter names (e.g., “holding_cost”) and the values equal the parameter values (e.g., 0.5).- Return type
dict or
SupplyChainNetwork
- Raises
ValueError – If the JSON file does not exist or the instance cannot be found in the JSON file.
- save_instance(instance_name, instance_data, instance_description='', filepath=None, replace=True, create_if_none=True, omit_state_vars=True)[source]¶
Save an instance to a JSON file.
- Parameters
instance_name (str) – The name of the instance. This will be used later for retreving the instance.
instance_data (dict or SupplyChainNetwork) – The instance data as a dictionary (with keys equal to parameter names (e.g., “holding_cost”) and values equal to parameter values (e.g., 0.5)) or as a
SupplyChainNetwork
object (in which case the instance is serialized usingjsonpickle
).instance_description (str, optional) – A longer descrtiption of the instance.
filepath (str, optional) – Path to the JSON file. If
None
, the function determines the path todatasets/stockpyl_instances.json
.replace (bool, optional) – If an instance with the same
instance_name
is already in the file, the function will replace it ifTrue
and will ignore it (and write nothing) ifFalse
.create_if_none (bool, optional) – If the file does not already exist, the function will create a new file if
True
; otherwise, it will not do anything and issue a warning.omit_state_vars (bool, optional) – If
True
, the function will not save state variables as part of the nodes, even if they are present in the instance.