Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Ervin66 authored Jun 22, 2021
1 parent 3778591 commit 2fd0a57
Show file tree
Hide file tree
Showing 3 changed files with 846 additions and 38 deletions.
87 changes: 49 additions & 38 deletions Model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,52 +21,51 @@ def __init__(self, data_path, product_col, time_col, loc_col, qty_col, service_l
self.qty_col = qty_col

self.raw_data = pd.read_csv(data_path,
nrows=1500)
nrows=100)
self.service_level = service_level
# column's values are converted to datetime_col objects to facilitate weekly aggregation
self.raw_data[time_col] = pd.to_datetime(self.raw_data[time_col])

# remove orders that do not have a location specified
self.raw_data = self.raw_data[self.raw_data[loc_col].notna()]
self.data = self.raw_data[self.raw_data[loc_col].notna()]
self.data = self.data.set_index([self.product_col, self.time_col, self.loc_col])

# privremeno
# v = self.raw_data[product_col].value_counts()
# self.raw_data = self.raw_data[self.raw_data[product_col].isin(
# v.index[v.gt(1000)])]

op_dic = {self.qty_col: "sum",
"hold_cost_pallet": "first",
"lead_time": "first",
"std_lead_time": "first",
}
self.data = self.raw_data.groupby([self.raw_data[time_col].dt.isocalendar().week,
product_col,
loc_col], dropna=False).agg(op_dic) # aggregate the order per week, product group and location

print(self.data.groupby(product_col)[
self.qty_col].agg(Mean='mean', Sum='sum', Size="size"))
self.data.to_csv("demand_input.csv")
self.inv_model = pulp.LpProblem("Inventory_Optimization",
LpMinimize) # creates an object of an LpProblem (PuLP) to which we will assign variables, constraints and objective function

def define_indices(self, new_time_col):
def define_indices(self):
''' Returns the unique values for indices from the input data
Required keywords argument:
new_time_col: string of the aggregation basis for time (e.g. "week", "month",...)
'''
self.prod_id = self.data.index.get_level_values(
self.product_col).unique().tolist()
self.time_id = self.data.index.get_level_values(
new_time_col).unique().tolist()
self.time_col).unique().tolist()
self.loc_id = self.loc_data.index
self.factory_id = self.loc_data[self.loc_data["Echelon"]
== "Factory"].index.tolist()
self.dc_id = self.loc_data[self.loc_data["Echelon"]
== "DC"].index.tolist()
self.wh_id = self.loc_data[self.loc_data["Echelon"]
== "Warehouse"].index.tolist()


# self.loc_data = self.loc_data.loc[self.loc_id]
# self.FTL_matrix = self.FTL_matrix.drop("CoP NL", axis=1) #temp

print(f"Number of product: {len(self.prod_id)}" + "\n",
f"Number of locations: {len(self.loc_id)}" + "\n",
f"Number of periods: {len(self.time_id)}")

def define_paramaters(self, loc_data_path, ftl_matrix):
''' Returns a dataframe of the paramaters required for the model
loc_data_path: string of the path to the location data
Expand All @@ -88,9 +87,9 @@ def define_paramaters(self, loc_data_path, ftl_matrix):
self.lt_df["var_lead_time"] = self.lt_df["std_lead_time"] ** 2
self.holding_costs = self.data.groupby(
["sh_ItemId", "sh_OriginLocationMasterLocation"])["hold_cost_pallet"].first()
print(self.holding_costs)
self.ss_df = self.compute_ss(self.service_level)

self.ss_df = self.compute_ss(self.service_level)

def define_variables(self):
'''Defines the variable and their nature whcih are then added to the model
'''
Expand Down Expand Up @@ -132,7 +131,7 @@ def define_objective(self):
''' Defines the objective funciton
'''
start_time = time.time()
holding_costs = lpSum([self.inv_level[i][w][t] * self.holding_costs.loc[i,w]
holding_costs = lpSum([self.inv_level[i][w][t] * self.holding_costs.loc[i, w]
for i in self.prod_id
for w in self.loc_id
for t in self.time_id
Expand Down Expand Up @@ -163,61 +162,60 @@ def define_constraints(self):
'''
start_time = time.time()


for f in self.factory_id:
for ind, t in enumerate(self.time_id):
self.inv_model += lpSum((self.inv_level[i][f][t]
for i in self.prod_id)) <= self.loc_data.loc[f, "Hold. Cap."]
self.inv_model += lpSum([self.inv_level[i][f][t]
for i in self.prod_id]) <= self.loc_data.loc[f, "Hold. Cap."]
for i in self.prod_id:
lt = self.time_id[max(int(
ind - self.lt_df.loc[i, "lead_time"]), 0)]
self.inv_model += lpSum((self.production[i][f][t]
for i in self.prod_id)) <= self.loc_data.loc[f, "Prod. Cap."]
self.inv_model += lpSum([self.production[i][f][t]
for i in self.prod_id]) <= self.loc_data.loc[f, "Prod. Cap."]
prevt = self.time_id[ind - 1]
self.inv_model += lpSum((self.inv_level[i][f][prevt] -
self.inv_model += lpSum([self.inv_level[i][f][prevt] -
self.data["Pallets"].get(
(t, i, f), 0)
- self.shipment[f][dc][i][t]
- self.shipment[f][w][i][t]
+ self.production[i][f][lt]
for dc in self.dc_id
for w in self.wh_id)) >= self.inv_level[i][f][t]
for w in self.wh_id]) >= self.inv_level[i][f][t]

for d in self.dc_id:
for ind, t in enumerate(self.time_id):
self.inv_model += lpSum((self.inv_level[i][d][t] + self.ss_df.loc[i, "central_wh"]
for i in self.prod_id)) <= self.loc_data.loc[d, "Hold. Cap."]
self.inv_model += lpSum([self.inv_level[i][d][t] + self.ss_df.loc[i, "central_wh"]
for i in self.prod_id]) <= self.loc_data.loc[d, "Hold. Cap."]
for i in self.prod_id:
prevt = self.time_id[max(ind - 1, 0)]
self.inv_model += lpSum((self.shipment[o][d][i][prevt] +
self.inv_model += lpSum([self.shipment[o][d][i][prevt] +
self.inv_level[i][d][prevt] -
self.data["Pallets"].get(
(t, i, d), 0)
- self.shipment[d][wh][i][t]
for o in self.factory_id
for wh in self.wh_id)) >= self.inv_level[i][d][t] + self.ss_df["central_wh"].get(i, 0)
for wh in self.wh_id]) >= self.inv_level[i][d][t] + self.ss_df["central_wh"].get(i, 0)

for d in self.wh_id:
for ind, t in enumerate(self.time_id):
self.inv_model += lpSum((self.inv_level[i][d][t] + self.ss_df.loc[i, "regional_wh"]
for i in self.prod_id)) <= self.loc_data.loc[d, "Hold. Cap."]
self.inv_model += lpSum([self.inv_level[i][d][t] + self.ss_df.loc[i, "regional_wh"]
for i in self.prod_id]) <= self.loc_data.loc[d, "Hold. Cap."]
for i in self.prod_id:
prevt = self.time_id[max(ind - 1, 0)]
self.inv_model += lpSum((self.shipment[o][d][i][prevt] +
self.inv_model += lpSum([self.shipment[o][d][i][prevt] +
self.shipment[f][d][i][prevt] +
self.inv_level[i][d][prevt] -
self.data["Pallets"].get(
(t, i, d), 0)
for f in self.factory_id
for o in self.dc_id)) >= self.inv_level[i][d][t] + self.ss_df["regional_wh"].get(i, 0)
for o in self.dc_id]) >= self.inv_level[i][d][t] + self.ss_df["regional_wh"].get(i, 0)

for o in self.factory_id + self.dc_id:
for d in self.dc_id + self.wh_id:
for t in self.time_id:
self.inv_model += lpSum((
self.inv_model += lpSum([
self.shipment[o][d][i][t] *
(1 / 33)
for i in self.prod_id)) == self.FTL[o][d][t]
for i in self.prod_id]) == self.FTL[o][d][t]
print("--- %s seconds ---" % (time.time() - start_time))
print("constraints defined")

Expand All @@ -237,8 +235,9 @@ def weighted_avg(self, time_ind, wh_ind, prod_ind):
def compute_ss(self, service_level):

ss_cw = self.service_level * (self.lt_df["lead_time"] * self.demand_stats["var"] +
self.demand_stats["mean"]**2 * self.lt_df["var_lead_time"])**0.5
ss_rw = self.service_level * (self.lt_df["lead_time"] * self.demand_stats["var"])**0.5
self.demand_stats["mean"]**2 * self.lt_df["var_lead_time"])**0.5
ss_rw = self.service_level * \
(self.lt_df["lead_time"] * self.demand_stats["var"])**0.5
ss_dic = {"central_wh": ss_cw, "regional_wh": ss_rw}
return pd.DataFrame(data=ss_dic, index=self.demand_stats.index)

Expand Down Expand Up @@ -298,6 +297,7 @@ def export_vars_3d(self, time_ind, wh_ind, prod_ind, variable, filename):
variable: variable name to be exported
filename: under which name to save the varaible to be exported to csv
'''
start_time = time.time()
dic = {"time": [], "warehouse": [], "product": [], "value": []}
for t in time_ind:
for w in wh_ind:
Expand All @@ -310,8 +310,11 @@ def export_vars_3d(self, time_ind, wh_ind, prod_ind, variable, filename):
self.var_df = self.var_df.fillna(0)
self.var_df.to_csv(filename + ".csv")
print(self.var_df)
print("--- %s seconds ---" % (time.time() - start_time))
print(f"{filename} exported")

def export_vars_4d(self, time_ind, origin_ind, destination_ind, prod_ind, variable, filename):
start_time = time.time()
dic = {"time": [], "origin": [],
"destination": [], "product": [], "value": []}
for t in time_ind:
Expand All @@ -328,18 +331,26 @@ def export_vars_4d(self, time_ind, origin_ind, destination_ind, prod_ind, variab
self.var_df = self.var_df[self.var_df["value"] > 0]
self.var_df.to_csv(filename + ".csv")
print(self.var_df)
print("--- %s seconds ---" % (time.time() - start_time))
print(f"{filename} exported")


# Actually creating an instance of the classes in which the model is defined
s = 1.95
time_dic = {}

start_time = time.time()
I = InventoryModel(data_path="./CSV input files/orders_abc_xyz.csv",
product_col="sh_ItemId",
time_col="sh_ShipmentDate",
loc_col="sh_OriginLocationMasterLocation",
loc_col="new_shOrigin",
qty_col="Pallets",
service_level=s)
# calling the function that will assemble the model together
I.build_model()
time_taken = time.time() - start_time
print("Total Time: ",time_taken)
time_dic[n] = time_taken



'''
Expand Down
Loading

0 comments on commit 2fd0a57

Please sign in to comment.