SupplyChainModeling
Installation
SupplyChainModeling can be installed using the Julia package manager. From the Julia REPL, type ] to enter the Pkg REPL mode and run
pkg> add SupplyChainModelingAPI
SupplyChainModeling.ConcreteNode — Type
ConcreteNodeThe closed set of built-in Node subtypes that participate in the lane-based flow network (Lane, SupplyChain.lanes_in/lanes_out, get_location_index). Hot-path type signatures use this instead of the bare abstract Node so Julia can compile dispatch as a handful of concrete branches (union-splitting) instead of a fully dynamic call - Node itself stays open for extension, but anything typed ConcreteNode needs updating (here) if a new Node subtype is added and should participate in those dispatch-efficient paths.
MaturationSource and QuotaSink are deliberately not part of this union: they connect through direct distance-based costing rather than Lanes (see SupplyChainOptimization.create_maturation_scheduling_model), so they never appear as a Lane origin/destination or in the lane-indexed dictionaries this union exists to speed up.
SupplyChainModeling.Customer — Type
A customer.
SupplyChainModeling.Demand — Type
The demand a customer has for a product.
SupplyChainModeling.IndexedCollection — Type
IndexedCollection{T}A stable ordering of a SupplyChain's nodes/products alongside a Dict{T, Int64} mapping each one to its position in that ordering.
Consumers like SupplyChainSimulation.State need to translate a Storage/ Product/location object into an integer index for direct array access on every inventory read/write; this pairs that translation Dict with the Vector it was built from so both can be handed out together, computed once (see get_storage_index/get_product_index/get_location_index below) instead of every State re-deriving its own copy.
SupplyChainModeling.Lane — Type
A transportation lane between two or more nodes of the supply chain.
SupplyChainModeling.Location — Type
The geographical location of a node of the supply chain. The location is defined by its latitude and longitude, and an optional name.
country is the ISO 3166-1 alpha-2 country code (e.g. "US", "CN") used to look up tariff rates between locations (see Tariff); it defaults to nothing, meaning the location isn't assigned to a customs territory and never triggers a tariff.
SupplyChainModeling.MaturationSource — Type
A single-batch production source whose product's value is a function of how long it has been held (see get_maturity_value) - the batch's age-value curve. This generalizes two families of problems that the operations-research literature usually treats separately:
- Perishable/deteriorating inventory (Nahmias, 1982; Goyal and Giri, 2001): value is typically flat, then drops to zero at a fixed shelf life, or decays continuously from the moment of production.
- Harvest/maturity scheduling (e.g. sugarcane or wine-grape harvest scheduling: fields/grapes ripen toward a peak, must be harvested within a window, and the mill/winery has a periodic intake capacity): value rises toward an ideal window before falling off if held too long.
Both are the same underlying object - a batch whose eligibility and value for shipment is age_value_curve(duration) - differing only in the curve's shape. add_product! has a convenient linear-growth-with-percentage-bands form for the common (harvest-scheduling-style) case, and a fully custom form accepting arbitrary value/feasible/penalty functions for anything else, including classical shelf-life curves.
A MaturationSource holds at most one batch per planning horizon ("all-in-all-out"): once a batch is started, the source cannot start another until that batch has shipped and, optionally, a changeover_periods-long turnaround has elapsed.
SupplyChainModeling.Node — Type
A node of the supply chain.
SupplyChainModeling.Plant — Type
A plant.
SupplyChainModeling.Product — Type
A product in the supply chain.
zones are the shipping zone multipliers applied to lane costs for this product (see Lane's unit_cost); it defaults to [1.0], a single zone with no adjustment.
SupplyChainModeling.QuotaSink — Type
A demand point with a soft periodic quota: deliveries of a product are not capped, but any shortfall or excess relative to the quota is penalized per unit rather than forbidden. This generalizes supply-managed quota systems (e.g. Canadian poultry/egg/dairy production quotas) and any other contractual periodic delivery target that a business would rather miss (at a cost) than treat as a hard constraint.
SupplyChainModeling.Storage — Type
A storage location.
SupplyChainModeling.Supplier — Type
A supplier.
SupplyChainModeling.SupplyChain — Type
The supply chain.
SupplyChainModeling.Tariff — Type
An ad-valorem tariff applied to a product moving from one customs territory to another.
rate is the fraction (e.g. 0.25 for 25%) applied to the product's declared value when a unit crosses from origin_country into destination_country. product is nothing to mean "every product" moving between the two countries.
Countries are matched against Location.country; a Lane whose origin and destination resolve to the same country (or where either side has no country set) never incurs a tariff.
SupplyChainModeling.Transport — Type
A means of moving product between nodes of the supply chain (see Lane).
SupplyChainModeling.VehicleType — Type
A type of vehicle available to move product between nodes of the supply chain.
SupplyChainModeling.add_customer! — Method
add_customer!(supply_chain, customer)Adds a customer to the supply chain.
SupplyChainModeling.add_demand! — Method
add_demand!(supply_chain, demand)Adds demand to the supply chain.
SupplyChainModeling.add_demand! — Method
add_demand!(supply_chain, customer, product, demand::Array{Float64, 1}; service_level=1.0)Adds customer demand for a product. The demand is specified for each time period.
The keyword arguments are:
service_level: indicates how many lost sales are allowed as a ratio of demand. No demand can be lost if the service level is 1.0 and all demand can be lost if the service level is 0.0.sales_price: the sales price of a unit of product.lost_sales_cost: the cost of losing the sales of a unit of product.
SupplyChainModeling.add_lane! — Method
add_lane!(supply_chain, lane)Adds a transportation lane to the supply chain.
SupplyChainModeling.add_maturation_source! — Method
add_maturation_source!(supply_chain, source)Adds a maturation source to the supply chain.
SupplyChainModeling.add_plant! — Method
add_plant!(supply_chain, plant)Adds a plant to the supply chain.
SupplyChainModeling.add_product! — Method
add_product!(source::MaturationSource, product, value_function, feasible_duration, duration_penalty; initial_inventory=0.0)Advanced form of add_product!: registers product on source with a fully custom age-value curve, instead of the linear-growth-with-percentage-bands convenience form below. Useful for anything that form can't express - for example, a classical shelf-life curve (constant value, infeasible to ship past a fixed age):
add_product!(source, product,
duration -> 1.0, # value_function: constant per-unit value
duration -> duration <= 5, # feasible_duration: sellable for 5 periods
duration -> 0.0) # duration_penalty: no partial-quality penaltyvalue_function(duration): the batch's value after being helddurationperiods.feasible_duration(duration): whether a batch may ship after being helddurationperiods.duration_penalty(duration): the per-unit cost of shipping afterdurationperiods (zero within the curve's ideal range).initial_inventory: if greater than zero, this source already holds a batch of this size at the start of the planning horizon (with current valuevalue_function(0)), which must ship during the horizon rather than being a free scheduling choice.
SupplyChainModeling.add_product! — Method
add_product!(source::MaturationSource, product; initial_value, maturation_rate, target_value,
acceptable_deviation_under, acceptable_deviation_over,
extended_deviation_under=0.0, extended_deviation_over=0.0,
underrun_unit_penalty=0.0, overrun_unit_penalty=0.0,
initial_inventory=0.0)Indicates that a MaturationSource can hold a batch of product, whose value grows linearly while held, toward a target with percentage-based tolerance bands - a convenience over the fully custom add_product! method above, for this common case (see MaturationSource's own docstring for the harvest-scheduling problems this shape fits).
The keyword arguments are:
initial_value: the value (e.g. weight) of the product when a batch starts, or its current value ifinitial_inventoryis greater than zero (i.e. a batch is already in progress at the start of the planning horizon).maturation_rate: the value gained per period a batch is held.target_value: the ideal value at the time a batch ships.acceptable_deviation_under,acceptable_deviation_over: the maximum deviation below/abovetarget_value(as a fraction of it) still considered on-target.extended_deviation_under,extended_deviation_over: additional deviation below/above the acceptable range (again as a fraction oftarget_value) that is still sellable, e.g. to an alternative market, subject tounderrun_unit_penalty/overrun_unit_penalty. A batch whose value falls outside even this extended range cannot ship.underrun_unit_penalty,overrun_unit_penalty: the cost per unit of value deviation fromtarget_valuefor a batch that ships within the extended-but-not-acceptable range.initial_inventory: if greater than zero, this source already holds a batch of this size at the start of the planning horizon (with current valueinitial_value), which must ship during the horizon rather than being a free scheduling choice.
SupplyChainModeling.add_product! — Method
add_product!(plant::Plant, product::Product; bill_of_material::Dict{Product, Float64}, unit_cost, maximum_throughput)Indicates that a plant can produce a product.
The keyword arguments are:
bill_of_material: the amount of other product needed to produce one unit of the product. This dictionary can be empty if there are no other products needed.unit_cost: the cost of producing one unit of product.maximum_throughput: the maximum amount of product that can be produced in a time period.time: the production lead time.
SupplyChainModeling.add_product! — Method
add_product!(sink::QuotaSink, product; quota, underproduction_unit_penalty=0.0, overproduction_unit_penalty=0.0)Indicates that a QuotaSink has a periodic delivery quota for product.
The keyword arguments are:
quota: the target quantity ofproductto be delivered in each period.underproduction_unit_penalty: the cost per unit delivered belowquotain a period.overproduction_unit_penalty: the cost per unit delivered abovequotain a period.
SupplyChainModeling.add_product! — Method
add_product!(storage::Storage, product; initial_inventory::Real=0,
unit_handling_cost::Real=0,
unit_holding_cost::Real=0,
maximum_throughput::Float64=Inf,
additional_stock_cover::Real=0.0,
maximum_units::Real=Inf,
overflow_unit_cost::Real=0.0)Indicates that a storage can store a product.
The keyword arguments are: - initial_inventory: the amount of product initially at the storage location - unit_handling_cost: : the cost of handling a unit of product at the storage location - unit_holding_cost: the cost of holding a unit of product at the storage location per period - maximum_throughput: the maximum number of units of product that can be sent per period - maximum_units: the maximum number of units of product that can be stored at the storage location at once - overflow_unit_cost: the cost per unit per period charged when more inventory arrives than maximum_units allows (e.g. temporary/overflow storage); the excess is delayed rather than lost
SupplyChainModeling.add_product! — Method
add_product!(supplier::Supplier, product::Product; unit_cost::Float64, maximum_throughput::Float64)Indicates that a supplier can provide a product.
The keyword arguments are:
unit_cost: the cost per unit of the product from this supplier.maximum_throughput: the maximum number of units that can be provided in each time period.
SupplyChainModeling.add_product! — Method
add_product!(supply_chain, product)Adds a product to the supply chain.
SupplyChainModeling.add_quota_sink! — Method
add_quota_sink!(supply_chain, sink)Adds a quota sink to the supply chain.
SupplyChainModeling.add_storage! — Method
add_storage!(supply_chain, storage)Adds a storage location to the supply chain.
SupplyChainModeling.add_supplier! — Method
add_supplier!(supply_chain, supplier)Adds a supplier to the supply chain.
SupplyChainModeling.add_tariff! — Method
add_tariff!(supply_chain, tariff::Tariff)Adds a tariff to the supply chain. A second Tariff for the same (origin_country, destination_country, product) replaces the first.
SupplyChainModeling.can_ship — Method
can_ship(lane::Lane, time::Int)Checks if inventory can be send on a lane at a given time.
SupplyChainModeling.get_arrivals — Method
get_arrivals(product::Product, lane::Lane, destination, time::Int)Gets the known inventory arrivals of a product on a lane for a given time.
SupplyChainModeling.get_demand — Method
get_demand(supply_chain, customer, product, time)Gets the demand of a customer for a product at a given time.
SupplyChainModeling.get_destinations — Method
get_destinations(lane::Lane)Gets the destinations of a lane.
SupplyChainModeling.get_fixed_cost — Method
get_fixed_cost(lane::Lane)Gets the fixed cost of using a lane.
SupplyChainModeling.get_initial_inventory — Method
get_initial_inventory(storage, product)Gets the inventory at the storage location at the start of the simulation.
SupplyChainModeling.get_lane_index — Method
get_lane_index(supply_chain::SupplyChain)::IndexedCollection{Lane}Gets supply_chain.lanes paired with a Dict{Lane, Int64} index into it, computed once and cached (see IndexedCollection).
Unlike get_storage_index/get_product_index/get_location_index, supply_chain.lanes is already a stable, insertion-ordered Array (not a Set), so items below is a copy() of it rather than a collect() of some other backing container - taken so the cached IndexedCollection stays an immutable snapshot decoupled from supply_chain.lanes (which add_lane! mutates in place with push!), same as the other three indices' relationship to the Sets they're built from.
SupplyChainModeling.get_lanes_between — Method
get_lanes_between(supply_chain, from, to)::Set{Lane}()Gets the lanes between two locations in the supply chain.
SupplyChainModeling.get_lanes_in — Method
get_lanes_in(supply_chain, node)::Set{Lane}()Gets the lanes going into a node in the supply chain.
SupplyChainModeling.get_lanes_out — Method
get_lanes_out(supply_chain, node)::Set{Lane}()Gets the lanes coming out of a node in the supply chain.
SupplyChainModeling.get_leadtime — Method
get_leadtime(lane::Lane, destination::ConcreteNode)Gets the lead time to reach a destination using a lane.
SupplyChainModeling.get_leadtime — Method
get_leadtime(lane::Lane, destination::Int64)Gets the lead time to reach the destination at the given index in lane.destinations. Prefer the ConcreteNode-based overload below when you have the destination itself rather than its index.
SupplyChainModeling.get_location_index — Method
get_location_index(supply_chain::SupplyChain)::IndexedCollection{ConcreteNode}Gets every Storage/Customer/Supplier in supply_chain (Plants are not a "location" in this sense - see get_locations in SupplyChainSimulation.jl) as a stable Vector paired with a Dict{ConcreteNode, Int64} index into it, computed once and cached (see IndexedCollection).
SupplyChainModeling.get_maturity_value — Method
get_maturity_value(source::MaturationSource, product, duration)Gets the expected batch value (e.g. weight) of product at source after being held for duration periods, per the source's registered age-value curve (see add_product!).
SupplyChainModeling.get_maximum_age — Method
get_maximum_age(node, product)Gets the maximum age (in time periods) that a unit of product may be held at a node.
SupplyChainModeling.get_maximum_overall_throughput — Method
get_maximum_overall_throughput(storage::Storage)Gets the maximum combined throughput (across all products) of a storage location.
SupplyChainModeling.get_maximum_storage — Method
get_maximum_storage(node, product)Gets the maximum number of units of product that can be stored at a node.
SupplyChainModeling.get_maximum_throughput — Method
get_maximum_throughput(node, product)Gets the maximum throughput for a product at a given node.
SupplyChainModeling.get_overflow_cost — Method
get_overflow_cost(node, product)Gets the per-unit-per-period cost charged for inventory that exceeds maximum_units and must be held in temporary overflow storage.
SupplyChainModeling.get_product_index — Method
get_product_index(supply_chain::SupplyChain)::IndexedCollection{Product}Gets supply_chain.products as a stable Vector paired with a Dict{Product, Int64} index into it, computed once and cached (see IndexedCollection).
SupplyChainModeling.get_storage_index — Method
get_storage_index(supply_chain::SupplyChain)::IndexedCollection{Storage}Gets supply_chain.storages as a stable Vector paired with a Dict{Storage, Int64} index into it, computed once and cached (see IndexedCollection).
SupplyChainModeling.get_tariff_rate — Method
get_tariff_rate(supply_chain, origin_country, destination_country, product)::Float64Gets the ad-valorem tariff rate (e.g. 0.25 for 25%) applied to product moving from origin_country to destination_country, falling back to a tariff registered for every product (see Tariff) between the two countries, or 0.0 if neither is registered.
SupplyChainModeling.has_product — Method
has_product(source::MaturationSource, product)Checks whether a MaturationSource is configured to hold batches of product (see add_product!).
SupplyChainModeling.has_product — Method
has_product(sink::QuotaSink, product)Checks whether a QuotaSink has a quota configured for product (see add_product!).
SupplyChainModeling.is_destination — Method
is_destination(location, lane::Lane)::boolChecks if a location is a destination of a lane.