Michael Lee

Python Transportation Model

Portfolio Optimization in Python

A Transport Optimization Model in Python

Transportation problems deal with efficiently allocating resources from supply to demand node given a cost function. Using linear optimization, these problems can be solved using computational methods via python and the module PuLP.

In the proposed model, there exists two supply nodes-- each with their own respective production quantities and labor costs-- who must ship to five markets of different distances and retail prices. The goal of the model can be either a) cost-minimization or b) profit-maximization.

Complete code and formal write-up can be found @Github

Setting up the Model

Firstly, the producer and consumer nodes are given supply and demand quantities. These are posed as a dictionary in Python, as the dictionary data-structure makes it easier, opposed to an array, to call data later on. Notice that in addition to the cites, a node warehouse is created as both a demand and supply node. The economic rational behind this is that any extra supply is not simply lost, but instead stored until the next period at a cost. Conversely, if demand is greater than total production, product can be shipped from the warehouse to satisfy demand. In addition to the labor cost and shipping cost at the warehouse, the goods stored incur some set depreciation rate.

# create a dict with the inventories of each warehouse
supply_0 = {'Sea': 1200,
'SD' : 600,
'Warehouse': 0}
demand_0 = {'Chi': 325,
'NY' : 300,
'Top': 275,
'Warehouse': 0}
# create labor price dict.
lab = {}
laborPrice = {'Sea': 3,
'SD': 2,
'Warehouse': 1}
# create sell price array
sellPrice_0 = {'Chi': 10,
'NY': 14,
'Top': 6,
'Warehouse': ((10+14+6)/3)* depreciation}

Next, we create a numpy array to house the distances Dij and the cost per mile along each route.

## create a time array
dist = np.array( #Destinations
# Chi NY Top Warehouse
[(29, 41, 26, 0),#Sea
(29, 40, 22, 0),#SD
( 0, 0, 0, 0) #Warehouse
])
# assuming hourly wage is 22USD
costMile = np.array([ #Destinations
#Chi NY Top Warehouse
(22, 22, 22, 22),#Sea
(22, 22, 22, 22),#SD
(22, 22, 22, 22) #Warehouse
])
view raw pythonCostMile hosted with ❤ by GitHub

Solving the Model with PuLP

Here is where the magic happens: we setup a linear system of equations which can be solved (read: optimized) via PuLP. By defining the cost function:

costi,j = distancei,j * wagei,j
we can minimize the cost subject to:
ΣSupply = ΣDemand

for key, Value in supply.items():
lab[key] = laborPrice[key] * Value
# create revenue matrix
rev = {}
for key, Value in demand.items():
rev[key] = Value * sellPrice[key]
# create a cost matrix and convert to a list
costs = (costMile * dist) / capacity
costs = costs.tolist()
costs = makeDict([Suppliers, Destinations], costs, 0)
# setup the cost minimization problem
prob = LpProblem('Canning Distribution Problem', LpMinimize)
# create a list of all possible routes
routes = [(S,D) for S in Suppliers for D in Destinations]
# create a dictionary to contain all referenced variables
route_var = LpVariable.dicts("Route", (Suppliers, Destinations), 0, None, LpInteger)
# add the objective function to the problem
prob += lpSum([route_var[S][D]*costs[S][D] for (S,D) in routes])
# constraints functions
for S in Suppliers:
prob += lpSum([route_var[S][D] for D in Destinations]) <= supply[S]
"sum_of_products_out_of_suppliers_%s" %S
for D in Destinations:
prob += lpSum([route_var[S][D] for S in Suppliers]) >= demand[D]
"sum_of_products_into_destinations_%s" %D
prob.writeLP('Transport_problem.lp')
prob.solve()
view raw transportpulpt hosted with ❤ by GitHub

Pulp then interprets the above and forms a separate .lp file which handles all the backend work. Simply put a print(value(prob.objective)) at the end and voila! There is your optimal route configuration.