supply_chain_network Module

Overview

This module contains the SupplyChainNetwork class, which is a network consisting of one or more nodes. The network and nodes 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 objects contained within the SupplyChainNetwork, rather than in the network itself.

API Reference

class SupplyChainNetwork(**kwargs)[source]

The SupplyChainNetwork class contains one or more nodes, each represented by a SupplyChainNode object.

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_time among all nodes in the network. Used by gsm_tree module.

Type

int

property nodes

List of all nodes in the network, as SupplyChainNode objects. Read only.

property node_indices

List of indices of all nodes in the network. Read only.

property source_nodes

List of all source nodes, i.e., all nodes that have no predecessors, as SupplyChainNode objects.

property sink_nodes

List of all sink nodes, i.e., all nodes that have no successors, as SupplyChainNode objects.

property edges

List of all edges, as tuples whose elements are the indices of the nodes in the edge.

has_directed_cycle()[source]

Check whether network contains a directed cycle.

Returns

True if network contains a directed cycle, False otherwise.

Return type

bool

initialize()[source]

Initialize the parameters in the object to their default values.

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

True if the two networks are equal, False otherwise.

Return type

bool

to_dict()[source]

Convert the SupplyChainNetwork object to a dict. Converts the object recursively, calling to_dict() on each SupplyChainNode in the network.

Returns

The dict representation of the network.

Return type

dict

classmethod from_dict(the_dict)[source]

Return a new SupplyChainNetwork object with attributes copied from the values in the_dict.

Parameters

the_dict (dict) – Dict representation of a SupplyChainNetwork, typically created using to_dict().

Returns

The object converted from the dict.

Return type

SupplyChainNetwork

get_node_from_index(index)[source]

Return node object with the specified index, or None if no matching node is found.

Parameters

index (int) – Index of node to find.

Returns

The node whose index is index, or None if none.

Return type

SupplyChainNode

reindex_nodes(old_to_new_dict, new_names=None)[source]

Change indices of the nodes in the network using old_to_new_dict. If new_names is provided, also updates name attribute 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 node to the network. node will not be connected to other nodes that might be in the network already.

If node is 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_node as a successor to node. node must already be contained in the network.

The method adds the nodes to each other’s lists of _successors and _predecessors. If successor_node is 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_node as a predecessor to node. node must already be contained in the network.

The method adds the nodes to each other’s lists of _successors and _predecessors. If predecessor_node is 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 node is not in the network (as determined by the index), do nothing.

Parameters

node (SupplyChainNode) – The node to remove.

networkx_digraph()[source]

Build a NetworkX DiGraph object with the same structure as the SupplyChainNetwork.

Returns

digraph – The networkx digraph object.

Return type

DiGraph

network_from_edges(edges, node_order_in_lists=None, **kwargs)[source]

Construct a supply chain network with the specified edges.

The kwargs parameters 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 None for 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_lists is provided, node_order_in_lists must contain the same indices as the nodes in the edges in edges (otherwise a ValueError is raised). The values in the list are assumed to correspond to the node indices in the order they are specified in node_order_in_lists. That is, the value in slot k in the parameter list is assigned to the node with index node_order_in_lists[k]. If a given node index is contained in the list of edges but is not in node_order_in_lists, the attribute value is set to None for that node.

  • If the parameter is a list and node_order_in_lists is 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 slot k in the parameter list is assigned to the node in slot k when the nodes in the edge list are sorted.

If edges is None or [], a single-node network is returned. The index of the node is set to 0, unless node_order_in_lists is provided, in which case the node’s index is set to node_order_in_lists[0]. The rules for kwargs above also apply to the single-node case.

The supply_type attribute is set to ‘U’ at all nodes that have no predecessors and to

None at all other nodes, no matter how (or whether) the corresponding parameter is set.

For the demand_source attribute, you may pass a DemandSource object or the individual attributes of the demand source (mean, round_to_int, etc.). In the latter case, a DemandSource object will be constructed with the specified attributes and filled into the demand_source attribute of the node. Note: If providing individual demand source attributes, the type attribute must be called demand_type to avoid ambiguity with other objects.

Similarly, you may pass Policy and DisruptionProcess objects for the inventory_policy and disruption_process attributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, the type attribute must be called policy_type to avoid ambiguity with other objects.

If kwargs contains a parameter that is not an attribute of SupplyChainNode or one of its attribute objects (DemandSource, Policy, or DisruptionProcess), an AttributeError is raised. (Exception: demand_type and policy_type are allowed even though they are not attributes of SupplyChainNode; see above.)

Note

This function does not check that valid attributes have been provided for demand_source, inventory_policy, and disruption_process. For example, it does not check that a base_stock_level has been provided if the policy type is set to BS.

Parameters
  • edges (list) – List of edges, with each edge specified as a tuple (a, b), where a is the index of the predecessor and b is the index of the successor node. If None or 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 the k th node.)

  • kwargs (optional) – Optional keyword arguments to specify node attributes.

Raises

AttributeError – If kwargs contains a parameter that is not an attribute of SupplyChainNode.

single_stage_system(index=0, **kwargs)[source]

Generate a single-stage network.

The kwargs parameters specify the attributes (data) for the node.

For the demand_source attribute, you may pass a DemandSource object or the individual attributes of the demand source (mean, round_to_int, etc.). In the latter case, a DemandSource object will be constructed with the specified attributes and filled into the demand_source attribute of the node. Note: If providing individual demand source attributes, the type attribute must be called demand_type to avoid ambiguity with other objects.

Similarly, you may pass Policy and DisruptionProcess objects for the inventory_policy and disruption_process attributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, the type attribute must be called policy_type to avoid ambiguity with other objects.

If kwargs contains a parameter that is not an attribute of SupplyChainNode or one of its attribute objects (DemandSource, Policy, or DisruptionProcess), an AttributeError is raised. (Exception: demand_type and policy_type are allowed even though they are not attributes of SupplyChainNode; see above.)

Note

This function does not check that valid attributes have been provided for demand_source, inventory_policy, and disruption_process. For example, it does not check that a base_stock_level has been provided if the policy type is set to BS.

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

SupplyChainNetwork

Raises

AttributeError – If kwargs contains a parameter that is not an attribute of SupplyChainNode.

Example (a SupplyChainNetwork object 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 setting node_order_in_system.

The kwargs parameters 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 in range(num_nodes), if node_order_in_system is not provided) but is not a key in the dict, the attribute value is set to None for 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_lists is provided, node_order_in_lists must contain the same indices as node_order_in_system (if it is provided) or 0, …, num_nodes - 1 (if it is not), otherwise a ValueError is raised. The values in the list are assumed to correspond to the node indices in the order they are specified in node_order_in_lists. That is, the value in slot k in the parameter list is assigned to the node with index node_order_in_lists[k].

  • If the parameter is a list and node_order_in_lists is not provided, the values in the list are assumed to correspond to nodes in the same order as node_order_in_system (or in range(num_nodes), if node_order_in_system is not provided).

demand_source and stockout_cost attributes are only set at the downstream-most node, no matter how (or whether) the corresponding parameter is set. supply_type attribute is set to ‘U’ at the upstream-most node and to None at all other nodes, no matter how (or whether) the corresponding parameter is set.

For the demand_source attribute, you may pass a DemandSource object or the individual attributes of the demand source (mean, round_to_int, etc.). In the latter case, a DemandSource object will be constructed with the specified attributes and filled into the demand_source attribute of the node. Note: If providing individual demand source attributes, the type attribute must be called demand_type to avoid ambiguity with other objects.

Similarly, you may pass Policy and DisruptionProcess objects for the inventory_policy and disruption_process attributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, the type attribute must be called policy_type to avoid ambiguity with other objects.

If kwargs contains a parameter that is not an attribute of SupplyChainNode or one of its attribute objects (DemandSource, Policy, or DisruptionProcess), an AttributeError is raised. (Exception: demand_type and policy_type are allowed even though they are not attributes of SupplyChainNode; see above.)

Note

This function does not check that valid attributes have been provided for demand_source, inventory_policy, and disruption_process. For example, it does not check that a base_stock_level has been provided if the policy type is set to BS.

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 the k th node.)

  • kwargs (optional) – Optional keyword arguments to specify node attributes.

Raises

AttributeError – If kwargs contains a parameter that is not an attribute of SupplyChainNode.

Example (a SupplyChainNetwork object 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
return network_from_edges(

edges=[], node_order_in_lists=[index], **kwargs

)

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_retailers are the retailers, but this can be changed by setting node_order_in_system.

The kwargs parameters 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 in range(num_nodes), if node_order_in_system is not provided) but is not a key in the dict, the attribute value is set to None for 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_lists is provided, node_order_in_lists must contain the same indices as the nodes in the edges in edges (otherwise a ValueError is raised). The values in the list are assumed to correspond to the node indices in the order they are specified in node_order_in_lists. That is, the value in slot k in the parameter list is assigned to the node with index node_order_in_lists[k]. If a given node index is contained in the list of edges but is not in node_order_in_lists, the attribute value is set to None for that node.

  • If the parameter is a list and node_order_in_lists is not provided, the values in the list are assumed to correspond to nodes in the same order as node_order_in_system (or in range(num_retailers+1), if node_order_in_system is not provided).

demand_source attribute 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 to None at all other nodes, no matter how (or whether) the corresponding parameter is set.

For the demand_source attribute, you may pass a DemandSource object or the individual attributes of the demand source (mean, round_to_int, etc.). In the latter case, a DemandSource object will be constructed with the specified attributes and filled into the demand_source attribute of the node. Note: If providing individual demand source attributes, the type attribute must be called demand_type to avoid ambiguity with other objects.

Similarly, you may pass Policy and DisruptionProcess objects for the inventory_policy and disruption_process attributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, the type attribute must be called policy_type to avoid ambiguity with other objects.

If kwargs contains a parameter that is not an attribute of SupplyChainNode or one of its attribute objects (DemandSource, Policy, or DisruptionProcess), an AttributeError is raised. (Exception: demand_type and policy_type are allowed even though they are not attributes of SupplyChainNode; see above.)

Note

This function does not check that valid attributes have been provided for demand_source, inventory_policy, and disruption_process. For example, it does not check that a base_stock_level has been provided if the policy type is set to BS.

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 the k th node.)

  • kwargs (optional) – Optional keyword arguments to specify node attributes.

Raises

AttributeError – If kwargs contains a parameter that is not an attribute of SupplyChainNode.

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_warehouses are the warehouses, but this can be changed by setting node_order_in_system.

The kwargs parameters 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 in range(num_nodes), if node_order_in_system is not provided) but is not a key in the dict, the attribute value is set to None for 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_lists is provided, node_order_in_lists must contain the same indices as the nodes in the edges in edges (otherwise a ValueError is raised). The values in the list are assumed to correspond to the node indices in the order they are specified in node_order_in_lists. That is, the value in slot k in the parameter list is assigned to the node with index node_order_in_lists[k]. If a given node index is contained in the list of edges but is not in node_order_in_lists, the attribute value is set to None for that node.

  • If the parameter is a list and node_order_in_lists is not provided, the values in the list are assumed to correspond to nodes in the same order as node_order_in_system (or in range(num_warehouses+1), if node_order_in_system is not provided).

demand_source attribute is only set at the retailer node, no matter how (or whether) the corresponding parameter is set. supply_type attribute is set to ‘U’ at the warehouse nodes and to None at the retailer node, no matter how (or whether) the corresponding parameter is set.

For the demand_source attribute, you may pass a DemandSource object or the individual attributes of the demand source (mean, round_to_int, etc.). In the latter case, a DemandSource object will be constructed with the specified attributes and filled into the demand_source attribute of the node. Note: If providing individual demand source attributes, the type attribute must be called demand_type to avoid ambiguity with other objects.

Similarly, you may pass Policy and DisruptionProcess objects for the inventory_policy and disruption_process attributes, or you may pass the individual attributes for these objects. Note: If providing individual inventory policy attributes, the type attribute must be called policy_type to avoid ambiguity with other objects.

If kwargs contains a parameter that is not an attribute of SupplyChainNode or one of its attribute objects (DemandSource, Policy, or DisruptionProcess), an AttributeError is raised. (Exception: demand_type and policy_type are allowed even though they are not attributes of SupplyChainNode; see above.)

Note

This function does not check that valid attributes have been provided for demand_source, inventory_policy, and disruption_process. For example, it does not check that a base_stock_level has been provided if the policy type is set to BS.

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 the k th node.)

  • kwargs (optional) – Optional keyword arguments to specify node attributes.

Raises

AttributeError – If kwargs contains a parameter that is not an attribute of SupplyChainNode.

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