Created
December 9, 2019 17:21
-
-
Save luthfianto/695696933c4af2f1745c1865d5f155e0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DF_COLUMN_NAME_DEALER = "Group Dealer Code" | |
## Formula | |
def f_RS_n(stock_nm1, distplan_n, target_n, target_np1): | |
def f_stock_n(stock_nm1, distplan_n, target_n): | |
return stock_nm1 + distplan_n - target_n | |
def _RS_n(stock_n, target_np1): | |
return stock_n / np.where(target_np1==0,1, target_np1) | |
return _RS_n(f_stock_n(stock_nm1, distplan_n, target_n), target_np1) | |
def f_RSSP_fullfilment(distplan_n, RSSP_n): | |
return distplan_n / np.where(RSSP_n==0,1, RSSP_n) | |
def f_OS_length_n(OS_nm1, SPK_n, distplan_n, target_np1): | |
def _f_OS_length_n(OS_n, target_np1): | |
return OS_n / np.where(target_np1==0,1, target_np1) | |
def _f_OS_n(OS_nm1, SPK_n, distplan_n): | |
return OS_nm1 + SPK_n - distplan_n | |
OS_n = _f_OS_n(OS_nm1, SPK_n, distplan_n) | |
return _f_OS_length_n(OS_n, target_np1) | |
def f_Target_fulfillment_n(stock_nm1, distplan_n, target_n): | |
return (stock_nm1 + distplan_n)/np.where(target_n==0,1, target_n) | |
""" | |
if distplan_n summed, it would be distplan - alloc = 0, because x-x = 0 | |
Sum RightHand. Scalar is okay | |
""" | |
def loss_RS(distplan_n, alloc, df, ByQty, goal = 'national'): | |
# Get series | |
stock_nm1_series = df["SRBy" + ByQty ] | |
target_n_series = df["TBy" + ByQty ] | |
target_np1_series = df["TBy" + ByQty +"P1" ] | |
# Get values of series | |
stock_nm1 = stock_nm1_series.values | |
target_n = target_n_series.values | |
target_np1 = target_np1_series.values | |
# y_pred | |
left = f_RS_n(stock_nm1, distplan_n, target_n, target_np1) | |
if goal == 'national': | |
# No-need to groupby | |
pass | |
elif goal == 'area': | |
# Group series by Area | |
stock_nm1 = stock_nm1_series.groupby('Area') | |
target_n_series = target_n_series.groupby('Area') | |
target_np1_series = target_np1_series.groupby('Area') | |
elif goal == 'dealer': | |
# Group series by Dealer | |
stock_nm1 = stock_nm1_series.groupby(DF_COLUMN_NAME_DEALER) | |
target_n_series = target_n_series.groupby(DF_COLUMN_NAME_DEALER) | |
target_np1_series = target_np1_series.groupby(DF_COLUMN_NAME_DEALER) | |
# Get from parameter | |
if type(goal) != str: | |
right = goal | |
else: | |
# Use previously (un/)aggregated values | |
stock_nm1 = stock_nm1_series.values | |
target_n = target_n_series.values | |
target_np1 = target_np1_series.values | |
right = f_RS_n(stock_nm1.sum(), alloc.sum(), target_n.sum(), target_np1.sum()) | |
return left - right | |
def loss_RSSP_fulfillment(distplan_n, alloc, df, ByQty, goal = 'national'): | |
RSSP_series = df["RSSP"] | |
RSSP = RSSP_series.values | |
left = f_RSSP_fullfilment(distplan_n, RSSP) | |
right =f_RSSP_fullfilment(alloc.sum(), RSSP.sum()) | |
if goal == 'national': | |
# No-need to groupby | |
pass | |
elif goal == 'area': | |
# Group series by Area | |
RSSP_series = RSSP_series.groupby('Area') | |
elif goal == 'dealer': | |
# Group series by Dealer | |
RSSP_series = RSSP_series.groupby(DF_COLUMN_NAME_DEALER) | |
# Get from parameter | |
if type(goal) != str: | |
right = goal | |
else: | |
# Use previously (un/)aggregated values | |
RSSP = RSSP_series.values | |
right = f_RSSP_fullfilment(alloc.sum(), RSSP.sum()) | |
return left - right | |
def loss_Target_fulfillment_n(distplan_n, alloc, df, ByQty, goal = 'national'): | |
stock_nm1_series = df["SRBy" + ByQty ] | |
target_n_series = df["TBy" + ByQty ] | |
stock_nm1 = stock_nm1_series.values | |
target_n = target_n_series.values | |
if goal == 'national': | |
# No-need to groupby | |
pass | |
elif goal == 'area': | |
# Group series by Area | |
stock_nm1_series = stock_nm1_series.groupby('Area') | |
target_n_series = target_n_series.groupby('Area') | |
elif goal == 'dealer': | |
# Group series by Dealer | |
stock_nm1_series = stock_nm1_series.groupby(DF_COLUMN_NAME_DEALER) | |
target_n_series = target_n_series.groupby(DF_COLUMN_NAME_DEALER) | |
# Get from parameter | |
if type(goal) != str: | |
right = goal | |
else: | |
# Use previously (un/)aggregated values | |
stock_nm1 = stock_nm1_series.values | |
target_n = target_n_series.values | |
right = f_Target_fulfillment_n(stock_nm1.sum(), alloc.sum(), target_n.sum()) | |
return left - right | |
class CostManager: | |
_loss_functions = { | |
"RS": loss_RS, | |
"RSSPFulfillment": loss_RSSP_fulfillment, | |
"TargetFulfillment": loss_Target_fulfillment_n, | |
"OSLength": loss_Target_fulfillment_n, | |
} | |
def __init__(self, df, allocation_series, cp_variable): | |
self._df = df | |
self._allocation_series = allocation_series | |
self._cx_var_distplan = cp_variable | |
# print("========") | |
# print(self._cx_var_distplan) | |
# print(self._cx_var_distplan.shape) | |
# print("========") | |
def _get_costs(self, selected_objectives): | |
cost_list = [] | |
for obj in selected_objectives: | |
print(obj) | |
by = obj.get("by") | |
if by: | |
ByQty = by + "Qty" | |
else: | |
ByQty=None | |
goal = obj.get("goal") or "national" | |
cost = self._loss_functions[obj["type"]]( | |
self._cx_var_distplan, self._allocation_series.sum(), self._df, ByQty, goal | |
) | |
cost_list.append(cost) | |
return cost_list | |
def _sumrank_cost_list(self, cost_list, cost_weights): | |
acc_cost = 0 | |
for idx in range(len(cost_list)): | |
curr_cost = cost_list[idx] | |
if cost_weights: | |
curr_weight = cost_weights[idx] | |
else: | |
curr_weight = 1 / (1 + idx) | |
# acc_cost = acc_cost + curr_weight * cp.sum_squares(cp.square(curr_cost)) | |
acc_cost = acc_cost + curr_weight * cp.sum_squares(curr_cost) | |
return acc_cost | |
def compute_cost(self, selected_objectives, objectives_weights=None): | |
if objectives_weights: | |
assert len(objectives_weights) == len(selected_objectives), (len(objectives_weights), len(selected_objectives)) | |
cost_list = self._get_costs(selected_objectives) | |
acc_cost = self._sumrank_cost_list(cost_list, objectives_weights) | |
return acc_cost |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment