import numpy as np
import gurobipy
from gurobipy import *
import matplotlib.pyplot as plt
###########NOTES###############
”’
The setup is as follows:
demand_node_demands—-> Vector of demands being sent to transhipment nodes.
supply_node_limit——> Supply nodes that receive from transshipment vertices
num_transhipment_nodes—> number of transhipment nodes receiving from demand nodes and sending to the supply node
load_limit—————> upper limit of load that can be put on any one transhipment node
demand——>Transshipment——>Supply
EXAMPLE of trivial setup where no nodes are overloaded:
demand_node_demands = [10,10,10] ——-> three demand nodes, sending 10 units each to transhipment nodes
supply_node_limit=[30] ——-> a single supply node that needs to receive 30 units total from transhipment nodes
num_transhipment_nodes = 3 ——-> three transhipment nodes that receive from demand nodes and send to supply nodes
load_limit = 20 ——-> if a transhipment node is sending+recieving more than 20 units it is ‘overloaded’
”’
def overloaded_trans_vertices(supply_node_limit, demand_node_demands, num_transhipment_nodes, load_limit, costs_S, costs_D):
m = Model(‘Min Buffered Number’)
T = num_transhipment_nodes
L = load_limit
num_supply = len(supply_node_limit)
num_demand = len(demand_node_demands)
# Variables
z = []
for i in range(T):
z.append(
m.addVar(lb=0, ub=GRB.INFINITY, obj=0, vtype=GRB.CONTINUOUS, name=”z” + str(i)))
S = [] # S[i,j]==number of units that supply node ‘j’ receives from transhipment node ‘i’
for j in range(T):
S.append([m.addVar(lb=0, ub=GRB.INFINITY, obj=0, vtype=GRB.CONTINUOUS)
for i in range(num_supply)])
D = [] # D[i,j]==number of units that demand node ‘i’ sends to transhipment node ‘j’
for i in range(num_demand):
D.append(
[m.addVar(lb=0, ub=GRB.INFINITY, obj=0, vtype=GRB.CONTINUOUS) for j in range(T)])
D=np.array(D)
S=np.array(S)
a = m.addVar(lb=0, ub=GRB.INFINITY, obj=0, vtype=GRB.CONTINUOUS, name=”a”)
# Objective
m.update()
m.setObjective(quicksum(z), GRB.MINIMIZE)
# Constraints
for i in range(T):
m.addConstr(z[i] >= quicksum(costs_S[i,j]*S[i,j]
for j in range(num_supply)) + quicksum(costs_D[j,i]*D[j,i] for j in range(num_demand)) – a * L + 1)
for i in range(num_demand):
m.addConstr(quicksum(D[i,j]
for j in range(T)) == a*demand_node_demands[i])
for j in range(num_supply):
m.addConstr(quicksum(S[i,j]
for i in range(T)) == a*supply_node_limit[j])
for i in range(T):
m.addConstr( -quicksum(S[i,j] for j in range(num_supply)) + quicksum(D[j,i] for j in range(num_demand)) == 0 )
m.optimize()
for i in range(D.shape[0]):
for j in range(D.shape[1]):
D[i,j]=D[i,j].X
for i in range(S.shape[0]):
for j in range(S.shape[1]):
S[i,j]=S[i,j].X
for i in range(T):
z[i]=z[i].X
a=a.X
return S,D,z,a
###############################################################################################
demand_node_demands = [10 for i in range(3)]
supply_node_limit=[10*10000]
num_transhipment_nodes = 3
load_limit = .7*supply_node_limit[0]/float(num_transhipment_nodes)
T = num_transhipment_nodes
num_demand = len(demand_node_demands)
num_supply = len(supply_node_limit)
costs_S=np.uniform( (T,num_supply) )
costs_D=np.uniform( (num_demand,T) )
S, D, z, a = overloaded_trans_vertices(
supply_node_limit, demand_node_demands, num_transhipment_nodes, load_limit, costs_S, costs_D)