supply_chain_network Module¶
Overview¶
This module contains the SupplyChainNetwork class, which is a network consisting of
one or more nodes and, optionally, one or more products. The network, nodes, and
products together specify a problem instance.
Note
The terms “node” and “stage” are used interchangeably in the documentation.
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).
A SupplyChainNetwork is used primarily for multi-echelon inventory optimization (MEIO)
or simulation. Most data for the problem instance is specified
in the SupplyChainNode and SupplyChainProduct objects contained within the SupplyChainNetwork, rather than in
the network itself.
API Reference¶
- class SupplyChainNetwork(**kwargs)[source]¶
The
SupplyChainNetworkclass contains one or more nodes, each represented by aSupplyChainNodeobject.- period¶
The current period. Used for simulation.
- Type
int
- problem_specific_data¶
Placeholder for object that is used to provide data for specific problem types.
- Type
object
- max_max_replenishment_time¶
Largest value of
max_replenishment_timeamong all nodes in the network. Used bygsm_treemodule.- Type
int
- property nodes¶
List of all nodes in the network, as
SupplyChainNodeobjects. Read only.
- property node_indices¶
List of indices of all nodes in the network. Read only.
- property nodes_by_index¶
A dict containing nodes in the network. The keys of the dict are node indices and the values are the corresponding
SupplyChainNodeobjects. For example,self.nodes_by_index[4]is aSupplyChainNodeobject with index 4. Read only.
- property products¶
List of all products in the network, as
SupplyChainProductobjects. Includes products that have been explicitly added to the network viaadd_product()as well as products that are handled by the nodes in the network. Read only.
- property product_indices¶
List of indices of all products in the network. Includes products that have been explicitly added to the network via
add_product()as well as products that are handled by the nodes in the network. Read only.
- property products_by_index¶
A dict containing products in the network. Includes products that have been explicitly added to the network via
add_product()as well as products that are handled by the nodes in the network.The keys of the dict are product indices and the values are the corresponding
SupplyChainProductobjects. For example,self.products_by_index[4]returns aSupplyChainProductobject for the product with index 4.Includes “dummy products” that are added internally to nodes that do not have a
SupplyChainProductobject added. Dummy products are identifiable as such by their index, which is always negative.Read only.
- property source_nodes¶
List of all source nodes, i.e., all nodes that have no predecessors, as
SupplyChainNodeobjects. Read only.
- property sink_nodes¶
List of all sink nodes, i.e., all nodes that have no successors, as
SupplyChainNodeobjects. Read only.
- property edges¶
List of all edges, as tuples whose elements are the indices of the nodes in the edge. Read only.
- has_directed_cycle()[source]¶
Check whether network contains a directed cycle.
- Returns
Trueif network contains a directed cycle,Falseotherwise.- Return type
bool
- deep_equal_to(other, rel_tol=1e-08)[source]¶
Check whether network “deeply equals”
other, i.e., if all attributes are equal, including attributes that are themselves objects.- Parameters
other (
SupplyChainNetwork) – The network to compare this one to.rel_tol (float, optional) – Relative tolerance to use when comparing equality of float attributes.
- Returns
Trueif the two networks are equal,Falseotherwise.- Return type
bool
- to_dict()[source]¶
Convert the
SupplyChainNetworkobject to a dict. Converts the object recursively, callingto_dict()on eachSupplyChainNodein the network.- Returns
The dict representation of the network.
- Return type
dict
- classmethod from_dict(the_dict)[source]¶
Return a new
SupplyChainNetworkobject with attributes copied from the values inthe_dict.- Parameters
the_dict (dict) – Dict representation of a
SupplyChainNetwork, typically created usingto_dict().- Returns
The object converted from the dict.
- Return type
- get_node_from_index(index)[source]¶
Return
SupplyChainNodeobject with the specified index, orNoneif no matching node is found.Deprecated since version 1.1: Use
node_from_indexinstead.- Parameters
index (int) – Index of node to find.
- Returns
The node whose index is
index, orNoneif none.- Return type
- reindex_nodes(old_to_new_dict, new_names=None)[source]¶
Change indices of the nodes in the network using
old_to_new_dict. Ifnew_namesis provided, also updatesnameattribute of the nodes.- Parameters
old_to_new_dict (dict) – Dict in which keys are old indices and values are new indices.
new_names (dict, optional) – Dict in which keys are old indices and values are new names.
- add_node(node)[source]¶
Add
nodeto the network.nodewill not be connected to other nodes that might be in the network already unless it has already been set as a predecessor or successor to another node in the network.If
nodeis already in the network (as determined by the index), do nothing.- Parameters
node (
SupplyChainNode) – The node to add to the network.
- add_edge(from_index, to_index)[source]¶
Add an edge to the network to and from the nodes with the specified indices. If the edge is already in the network, does nothing.
- Parameters
from_index (int) – Index of “from” node.
to_index (int) – Index of “to” node.
- Raises
ValueError – If either index is not in the network.
- add_edges_from_list(edge_list)[source]¶
Add multiple edges to the network from a list of index tuples. Any edge that is already in the network is ignored.
- Parameters
edge_list (list) – List of tuples of indices of nodes in edges.
- Raises
ValueError – If any of the nodes are not in the network.
- add_successor(node, successor_node)[source]¶
Add
successor_nodeas a successor tonode.nodemust already be contained in the network.The method adds the nodes to each other’s lists of successors and predecessors. If
successor_nodeis not already contained in the network, the method also adds it. (The node is assumed to be contained in the network if its index or name match those of a node in the network.)- Parameters
node (
SupplyChainNode) – The node to which the successor should be added.successor_node (
SupplyChainNode) – The node to be added as a successor.
- add_predecessor(node, predecessor_node)[source]¶
Add
predecessor_nodeas a predecessor tonode.nodemust already be contained in the network.The method adds the nodes to each other’s lists of successors and predecessors. If
predecessor_nodeis not already contained in the network, the method also adds it. (The node is assumed to be contained in the network if its index or name match those of a node in the network.)- Parameters
node (
SupplyChainNode) – The node to which the successor should be added.predecessor_node (
SupplyChainNode) – The node to be added as a predecessor.
- remove_node(node)[source]¶
Remove a node from the network. Remove the node from the node list and from its predecessors’ and successors’ successors and predecessors lists.
If
nodeis not in the network (as determined by the index), do nothing.- Parameters
node (
SupplyChainNode) – The node to remove.
- networkx_digraph()[source]¶
Build a NetworkX
DiGraphobject with the same structure as theSupplyChainNetwork.- Returns
digraph – The
networkxdigraphobject.- Return type
DiGraph
- add_product(product)[source]¶
Add
productto the network.productwill not automatically be contained in any nodes that might be in the network already. Ifproductis already in the network (as determined by the index), do nothing.It is not necessary to add products using this function if they are handled by nodes in the network. The only reason to use this function is to add a product to a network that is not handled by any node in the network, which is not typical, or when loading a network from a file..
- Parameters
product (
SupplyChainProduct) – The product to add locally to the network.
- remove_product(product)[source]¶
Remove a product from the network. If
productis not in the network (as determined by the index), do nothing.productmay be either aSupplyChainProductobject or the index of the product.The product is removed locally from the network itself but is not removed from any nodes within the network. If the product is handled by any of those nodes, it will still be included in
self.products.- Parameters
product (
SupplyChainProductor int) – The product to remove locally from the network.
- parse_node(node, allow_none=True)[source]¶
Return the node and node index as a tuple, whether
nodeis aSupplyChainNodeobject or an int.- Parameters
node (
SupplyChainNodeor int) – The node itself (as aSupplyChainNode) or its index (as an int).allow_none (bool, optional) – If
True(the default),nodemay beNone, in which case the function returnsNone, None. IfFalse, raises an exception.
- Returns
|class_node| – The node object.
int – The node index.
- Raises
TypeError – If
nodeis not aSupplyChainNodeor an int.ValueError – if
nodeis not a node in the network.
- parse_product(product, allow_none=True)[source]¶
Return the product and product index as a tuple, whether
productis aSupplyChainProductobject or an int.- Parameters
product (
SupplyChainProductor int) – The product itself (as aSupplyChainProduct) or its index (as an int).allow_none (bool, optional) – If
True(the default),productmay beNone, in which case the function returnsNone, None. IfFalse, raises an exception.
- Returns
|class_product| – The product object.
int – The product index.
- Raises
TypeError – If
productis not aSupplyChainProductor an int.ValueError – if
productis not a product in the network.
- network_from_edges(edges, node_order_in_lists=None, **kwargs)[source]¶
Construct a supply chain network with the specified edges.
The
kwargsparameters specify the attributes (data) for the nodes in the network. If they are provided, they must be either a dict, a list, or a singleton, with the following requirements:If the parameter is a dict, then the keys must contain the node indices and the values must contain the corresponding attribute values. If a given node index is contained in the list of edges but is not a key in the dict, the attribute value is set to
Nonefor that node.If the parameter is a singleton, then the attribute is set to that value for all nodes.
If the parameter is a list and
node_order_in_listsis provided,node_order_in_listsmust contain the same indices as the nodes in the edges inedges(otherwise aValueErroris raised). The values in the list are assumed to correspond to the node indices in the order they are specified innode_order_in_lists. That is, the value in slotkin the parameter list is assigned to the node with indexnode_order_in_lists[k]. If a given node index is contained in the list of edges but is not innode_order_in_lists, the attribute value is set toNonefor that node.If the parameter is a list and
node_order_in_listsis not provided, the values in the list are assumed to correspond to the sorted list of node indices in the edge list. That is, the value in slotkin the parameter list is assigned to the node in slotkwhen the nodes in the edge list are sorted.
If
edgesisNoneor[], a single-node network is returned. The index of the node is set to 0, unlessnode_order_in_listsis provided, in which case the node’s index is set tonode_order_in_lists[0]. The rules forkwargsabove also apply to the single-node case.- The
supply_typeattribute is set to ‘U’ at all nodes that have no predecessors and to Noneat all other nodes, no matter how (or whether) the corresponding parameter is set.
For the
demand_sourceattribute, you may pass aDemandSourceobject or the individual attributes of the demand source (mean,round_to_int, etc.). In the latter case, aDemandSourceobject will be constructed with the specified attributes and filled into thedemand_sourceattribute of the node. Note: If providing individual demand source attributes, thetypeattribute must be calleddemand_typeto avoid ambiguity with other objects.Similarly, you may pass
PolicyandDisruptionProcessobjects for theinventory_policyanddisruption_processattributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, thetypeattribute must be calledpolicy_typeto avoid ambiguity with other objects.If
kwargscontains a parameter that is not an attribute ofSupplyChainNodeor one of its attribute objects (DemandSource,Policy, orDisruptionProcess), anAttributeErroris raised. (Exception:demand_typeandpolicy_typeare allowed even though they are not attributes ofSupplyChainNode; see above.)Note
This function does not check that valid attributes have been provided for
demand_source,inventory_policy, anddisruption_process. For example, it does not check that abase_stock_levelhas been provided if the policy type is set toBS.- Parameters
edges (list) – List of edges, with each edge specified as a tuple
(a, b), whereais the index of the predecessor andbis the index of the successor node. IfNoneor empty, a single-node network is created.node_order_in_lists (list, optional) – List of node indices in the order in which the nodes are listed in any attributes that are lists. (
node_order_in_lists[k]is the index of thekth node.)kwargs (optional) – Optional keyword arguments to specify node attributes.
- Raises
AttributeError – If
kwargscontains a parameter that is not an attribute ofSupplyChainNode.
- single_stage_system(index=0, **kwargs)[source]¶
Generate a single-stage network.
The
kwargsparameters specify the attributes (data) for the node.For the
demand_sourceattribute, you may pass aDemandSourceobject or the individual attributes of the demand source (mean,round_to_int, etc.). In the latter case, aDemandSourceobject will be constructed with the specified attributes and filled into thedemand_sourceattribute of the node. Note: If providing individual demand source attributes, thetypeattribute must be calleddemand_typeto avoid ambiguity with other objects.Similarly, you may pass
PolicyandDisruptionProcessobjects for theinventory_policyanddisruption_processattributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, thetypeattribute must be calledpolicy_typeto avoid ambiguity with other objects.If
kwargscontains a parameter that is not an attribute ofSupplyChainNodeor one of its attribute objects (DemandSource,Policy, orDisruptionProcess), anAttributeErroris raised. (Exception:demand_typeandpolicy_typeare allowed even though they are not attributes ofSupplyChainNode; see above.)Note
This function does not check that valid attributes have been provided for
demand_source,inventory_policy, anddisruption_process. For example, it does not check that abase_stock_levelhas been provided if the policy type is set toBS.- Parameters
index (int, optional) – Index to use for the node. Default = 0.
kwargs (optional) – Optional keyword arguments to specify node attributes.
- Returns
network – The single-stage network, with parameters filled.
- Return type
- Raises
AttributeError – If
kwargscontains a parameter that is not an attribute ofSupplyChainNode.
Example (a
SupplyChainNetworkobject containing the data from Example 4.1):>>> network = single_stage_system(holding_cost=0.18, ... stockout_cost=0.70, ... demand_type='N', ... mean=50, standard_deviation=8, ... policy_type='BS', ... base_stock_level=56.6) >>> network.nodes[0].stockout_cost 0.7
- serial_system(num_nodes, node_order_in_system=None, node_order_in_lists=None, **kwargs)[source]¶
Generate a serial system with the specified number of nodes. By default, node 0 is upstream and node
num_nodes- 1 is downstream, but this can be changed by settingnode_order_in_system.The
kwargsparameters specify the attributes (data) for the nodes in the network. If they are provided, they must be either a dict, a list, or a singleton, with the following requirements:If the parameter is a dict, then the keys must contain the node indices and the values must contain the corresponding attribute values. If a given node index is contained in
node_order_in_system(or inrange(num_nodes), ifnode_order_in_systemis not provided) but is not a key in the dict, the attribute value is set toNonefor that node.If the parameter is a singleton, then the attribute is set to that value for all nodes.
If the parameter is a list and
node_order_in_listsis provided,node_order_in_listsmust contain the same indices asnode_order_in_system(if it is provided) or 0, …,num_nodes- 1 (if it is not), otherwise aValueErroris raised. The values in the list are assumed to correspond to the node indices in the order they are specified innode_order_in_lists. That is, the value in slotkin the parameter list is assigned to the node with indexnode_order_in_lists[k].If the parameter is a list and
node_order_in_listsis not provided, the values in the list are assumed to correspond to nodes in the same order asnode_order_in_system(or inrange(num_nodes), ifnode_order_in_systemis not provided).
demand_sourceandstockout_costattributes are only set at the downstream-most node, no matter how (or whether) the corresponding parameter is set.supply_typeattribute is set to ‘U’ at the upstream-most node and toNoneat all other nodes, no matter how (or whether) the corresponding parameter is set.For the
demand_sourceattribute, you may pass aDemandSourceobject or the individual attributes of the demand source (mean,round_to_int, etc.). In the latter case, aDemandSourceobject will be constructed with the specified attributes and filled into thedemand_sourceattribute of the node. Note: If providing individual demand source attributes, thetypeattribute must be calleddemand_typeto avoid ambiguity with other objects.Similarly, you may pass
PolicyandDisruptionProcessobjects for theinventory_policyanddisruption_processattributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, thetypeattribute must be calledpolicy_typeto avoid ambiguity with other objects.If
kwargscontains a parameter that is not an attribute ofSupplyChainNodeor one of its attribute objects (DemandSource,Policy, orDisruptionProcess), anAttributeErroris raised. (Exception:demand_typeandpolicy_typeare allowed even though they are not attributes ofSupplyChainNode; see above.)Note
This function does not check that valid attributes have been provided for
demand_source,inventory_policy, anddisruption_process. For example, it does not check that abase_stock_levelhas been provided if the policy type is set toBS.- Parameters
num_nodes (int) – Number of nodes in the serial system.
node_order_in_system (list, optional) – List of node indices in the order that they appear in the serial system, with upstream-most node listed first. If omitted, the system will be indexed 0, …,
num_nodes- 1.node_order_in_lists (list, optional) – List of node indices in the order in which the nodes are listed in any attributes that are lists. (
node_order_in_lists[k]is the index of thekth node.)kwargs (optional) – Optional keyword arguments to specify node attributes.
- Raises
AttributeError – If
kwargscontains a parameter that is not an attribute ofSupplyChainNode.
Example (a
SupplyChainNetworkobject containing the data from Example 4.1):>>> network = single_stage_system(holding_cost=0.18, ... stockout_cost=0.70, ... demand_type='N', ... mean=50, standard_deviation=8, ... policy_type='BS', ... base_stock_level=56.6) >>> network.nodes[0].stockout_cost 0.7
- owmr_system(num_retailers, node_order_in_system=None, node_order_in_lists=None, **kwargs)[source]¶
Generate a one-warehouse, multiple-retailer (OWMR) (i.e., 2-echelon distribution) system with the specified number of retailers. By default, node 0 is the warehouse and nodes 1, …,
num_retailersare the retailers, but this can be changed by settingnode_order_in_system.The
kwargsparameters specify the attributes (data) for the nodes in the network. If they are provided, they must be either a dict, a list, or a singleton, with the following requirements:If the parameter is a dict, then the keys must contain the node indices and the values must contain the corresponding attribute values. If a given node index is contained in
node_order_in_system(or inrange(num_nodes), ifnode_order_in_systemis not provided) but is not a key in the dict, the attribute value is set toNonefor that node.If the parameter is a singleton, then the attribute is set to that value for all nodes.
If the parameter is a list and
node_order_in_listsis provided,node_order_in_listsmust contain the same indices as the nodes in the edges inedges(otherwise aValueErroris raised). The values in the list are assumed to correspond to the node indices in the order they are specified innode_order_in_lists. That is, the value in slotkin the parameter list is assigned to the node with indexnode_order_in_lists[k]. If a given node index is contained in the list of edges but is not innode_order_in_lists, the attribute value is set toNonefor that node.If the parameter is a list and
node_order_in_listsis not provided, the values in the list are assumed to correspond to nodes in the same order asnode_order_in_system(or inrange(num_retailers+1), ifnode_order_in_systemis not provided).
demand_sourceattribute is not set at the warehouse node, no matter how (or whether) the corresponding parameter is set.``supply_type`` attribute is set to ‘U’ at the warehouse node and toNoneat all other nodes, no matter how (or whether) the corresponding parameter is set.For the
demand_sourceattribute, you may pass aDemandSourceobject or the individual attributes of the demand source (mean,round_to_int, etc.). In the latter case, aDemandSourceobject will be constructed with the specified attributes and filled into thedemand_sourceattribute of the node. Note: If providing individual demand source attributes, thetypeattribute must be calleddemand_typeto avoid ambiguity with other objects.Similarly, you may pass
PolicyandDisruptionProcessobjects for theinventory_policyanddisruption_processattributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, thetypeattribute must be calledpolicy_typeto avoid ambiguity with other objects.If
kwargscontains a parameter that is not an attribute ofSupplyChainNodeor one of its attribute objects (DemandSource,Policy, orDisruptionProcess), anAttributeErroris raised. (Exception:demand_typeandpolicy_typeare allowed even though they are not attributes ofSupplyChainNode; see above.)Note
This function does not check that valid attributes have been provided for
demand_source,inventory_policy, anddisruption_process. For example, it does not check that abase_stock_levelhas been provided if the policy type is set toBS.- Parameters
num_retailers (int) – Number of retailers in OWMR system.
node_order_in_system (list, optional) – List of node indices in the order that they appear in the OWMR system, with warehouse node first and retailer nodes last. If omitted, the warehouse will have index 0 and the retailers will have indices 1, …,
num_retailers.node_order_in_lists (list, optional) – List of node indices in the order in which the nodes are listed in any attributes that are lists. (
node_order_in_lists[k]is the index of thekth node.)kwargs (optional) – Optional keyword arguments to specify node attributes.
- Raises
AttributeError – If
kwargscontains a parameter that is not an attribute ofSupplyChainNode.
- mwor_system(num_warehouses, node_order_in_system=None, node_order_in_lists=None, **kwargs)[source]¶
Generate a multiple-warehouse, one-retailer (MWOR) (i.e., 2-echelon assembly) system with the specified number of warehouses. By default, node 0 is the retailer and nodes 1, …,
num_warehousesare the warehouses, but this can be changed by settingnode_order_in_system.The
kwargsparameters specify the attributes (data) for the nodes in the network. If they are provided, they must be either a dict, a list, or a singleton, with the following requirements:If the parameter is a dict, then the keys must contain the node indices and the values must contain the corresponding attribute values. If a given node index is contained in
node_order_in_system(or inrange(num_nodes), ifnode_order_in_systemis not provided) but is not a key in the dict, the attribute value is set toNonefor that node.If the parameter is a singleton, then the attribute is set to that value for all nodes.
If the parameter is a list and
node_order_in_listsis provided,node_order_in_listsmust contain the same indices as the nodes in the edges inedges(otherwise aValueErroris raised). The values in the list are assumed to correspond to the node indices in the order they are specified innode_order_in_lists. That is, the value in slotkin the parameter list is assigned to the node with indexnode_order_in_lists[k]. If a given node index is contained in the list of edges but is not innode_order_in_lists, the attribute value is set toNonefor that node.If the parameter is a list and
node_order_in_listsis not provided, the values in the list are assumed to correspond to nodes in the same order asnode_order_in_system(or inrange(num_warehouses+1), ifnode_order_in_systemis not provided).
demand_sourceattribute is only set at the retailer node, no matter how (or whether) the corresponding parameter is set.supply_typeattribute is set to ‘U’ at the warehouse nodes and toNoneat the retailer node, no matter how (or whether) the corresponding parameter is set.For the
demand_sourceattribute, you may pass aDemandSourceobject or the individual attributes of the demand source (mean,round_to_int, etc.). In the latter case, aDemandSourceobject will be constructed with the specified attributes and filled into thedemand_sourceattribute of the node. Note: If providing individual demand source attributes, thetypeattribute must be calleddemand_typeto avoid ambiguity with other objects.Similarly, you may pass
PolicyandDisruptionProcessobjects for theinventory_policyanddisruption_processattributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, thetypeattribute must be calledpolicy_typeto avoid ambiguity with other objects.If
kwargscontains a parameter that is not an attribute ofSupplyChainNodeor one of its attribute objects (DemandSource,Policy, orDisruptionProcess), anAttributeErroris raised. (Exception:demand_typeandpolicy_typeare allowed even though they are not attributes ofSupplyChainNode; see above.)Note
This function does not check that valid attributes have been provided for
demand_source,inventory_policy, anddisruption_process. For example, it does not check that abase_stock_levelhas been provided if the policy type is set toBS.- Parameters
num_warehouses (int) – Number of warehouses in MWOR system.
node_order_in_system (list, optional) – List of node indices in the order that they appear in the MWOR system, with warehouse nodes first and retailer node last. If omitted, the retailer will have index 0 and the warehouses will have indices 1, …,
num_warehouses.node_order_in_lists (list, optional) – List of node indices in the order in which the nodes are listed in any attributes that are lists. (
node_order_in_lists[k]is the index of thekth node.)kwargs (optional) – Optional keyword arguments to specify node attributes.
- Raises
AttributeError – If
kwargscontains a parameter that is not an attribute ofSupplyChainNode.
- local_to_echelon_base_stock_levels(network, S_local)[source]¶
Convert local base-stock levels to echelon base-stock levels for a serial system.
Assumes network is serial system but does not assume anything about the labeling of the nodes.
- Parameters
network (
SupplyChainNetwork) – The serial inventory network.S_local (dict) – Dict of local base-stock levels.
- Returns
S_echelon – Dict of echelon base-stock levels.
- Return type
dict
- echelon_to_local_base_stock_levels(network, S_echelon)[source]¶
Convert echelon base-stock levels to local base-stock levels for a serial system.
Assumes network is serial system but does not assume anything about the labeling of the nodes.
- Parameters
network (
SupplyChainNetwork) – The serial inventory network.S_echelon (dict) – Dict of echelon base-stock levels.
- Returns
S_local – Dict of local base-stock levels.
- Return type
dict