In [1]:
# Essentials
import pandas as pd
import numpy as np
import math
from math import *
# Visualization
import bokeh.plotting as bk
from bokeh.plotting import figure, show, output_file
import matplotlib.pyplot as plt
%matplotlib inline
In [2]:
# Input data
kitchen = pd.read_csv("input/kitchen.csv", error_bad_lines=False, engine="python", encoding = "ISO-8859-1")
customer = pd.read_csv("input/customer.csv", error_bad_lines=False, engine="python", encoding = "ISO-8859-1")
customer1 = pd.read_csv("input/customer.csv", error_bad_lines=False, engine="python", encoding = "ISO-8859-1")
kitchen1 = pd.read_csv("input/kitchen.csv", error_bad_lines=False, engine="python", encoding = "ISO-8859-1")
Kunci utama dari Efisiensi pengiriman menurut kami adalah customer harus terassign ke kitchen yang paling optimum dulu. Dimana kitchen optimum tidak selalu kitchen yang paling dekat dengan customer. Solusi optimum = Sort dari Outermost customer dan ada mekanisme penukaran apabila kitchen sudah full.
Karena susah, kami melakukan sedikit perubahan
-menSort customer dari jarak yang paling jauh dari titik pusat customer (sum/total lat long).
-assign customer ke kitchen terdekat
-apabila kitchen terdekat sudah full maka diassign ke kitchen kedua terdekat, dst.
Sehingga bisa didapat group berupa customer yang terassign ke suatu kitchen. Solusi tersebut belum optimal,tapi cukup mendekati.
Kurir kemudian di assign per group berdasarkan degree dan jarak. Kami berusaha mengoptimalkan waktu pengiriman selama satu jam (Sebisa mungkin kurir mendapat jarak yang sama, Tidak ada kurir yang terlalu cepat selesai atau terlalu lama selesai). Di assign tidak hanya berdasarkan jarak untuk mengoptimalkan waktu pengiriman selama 1 jam.
In [3]:
bk.output_notebook()
def mscatter(p, x, y, marker, color):
p.scatter(x, y, marker=marker, size=10,line_color="black", fill_color=color, alpha=1)
def mtext(p, x, y, text):
p.text(x, y, text=text, text_color="black", text_align="center", text_font_size="10pt")
p = figure(title="Persebaran Customer dan Kitchen",match_aspect=True, aspect_scale=1,plot_width=900)
p.grid.grid_line_color = None
p.background_fill_color = "#eeeeee"
#p.axis.visible = False
mscatter(p, customer['long'], customer['lat'], "circle", "red")
mscatter(p, kitchen['long'], kitchen['lat'], "square", "blue")
mtext(p, kitchen['long'], kitchen['lat'],["Dapur Miji","Dapur Nusantara","Familia Catering","Pondok Catering","Rose Catering","Tiga Kitchen Catering","Ummu Uwais"])
show(p)
In [4]:
# Find center point of customer, buat nyari
# long
long_centroid = sum(customer['long'])/len(customer)
# lat
lat_centroid = sum(customer['lat'])/len(customer)
In [5]:
p = figure(title="Persebaran Customer dan Titik Pusat Customer", match_aspect=True,aspect_scale=1, plot_width=900)
p.grid.grid_line_color = None
p.background_fill_color = "#eeeeee"
#p.axis.visible = False
mscatter(p, customer['long'], customer['lat'], "circle", "red")
mscatter(p, long_centroid, lat_centroid, "square", "blue")
mtext(p, long_centroid, lat_centroid, ["Titik Pusat Customer"])
show(p)
In [6]:
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
km = 6367 * c
return km
"""
customer1['dist0'] = ""
for i in customer1.index:
customer1['dist0'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[0],kitchen['lat'].iloc[0])
customer1['dist1'] = ""
for i in customer1.index:
customer1['dist1'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[1],kitchen['lat'].iloc[1])
customer1['dist2'] = ""
for i in customer1.index:
customer1['dist2'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[2],kitchen['lat'].iloc[2])
customer1['dist3'] = ""
for i in customer1.index:
customer1['dist3'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[3],kitchen['lat'].iloc[3])
customer1['dist4'] = ""
for i in customer1.index:
customer1['dist4'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[4],kitchen['lat'].iloc[4])
customer1['dist5'] = ""
for i in customer1.index:
customer1['dist5'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[5],kitchen['lat'].iloc[5])
customer1['dist6'] = ""
for i in customer1.index:
customer1['dist6'].loc[i] = haversine(customer1['long'].loc[i],customer1['lat'].loc[i],kitchen['long'].iloc[6],kitchen['lat'].iloc[6])
"""
# approximate distance in meter = euclidean distance * 111km
# not so accurate, but fast
customer1['dist0'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[0]])**2 + (customer.lat-[kitchen['lat'].iloc[0]]*len(customer))**2)
customer1['dist1'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[1]])**2 + (customer.lat-[kitchen['lat'].iloc[1]]*len(customer))**2)
customer1['dist2'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[2]])**2 + (customer.lat-[kitchen['lat'].iloc[2]]*len(customer))**2)
customer1['dist3'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[3]])**2 + (customer.lat-[kitchen['lat'].iloc[3]]*len(customer))**2)
customer1['dist4'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[4]])**2 + (customer.lat-[kitchen['lat'].iloc[4]]*len(customer))**2)
customer1['dist5'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[5]])**2 + (customer.lat-[kitchen['lat'].iloc[5]]*len(customer))**2)
customer1['dist6'] = 111*np.sqrt( (customer.long-[kitchen['long'].iloc[6]])**2 + (customer.lat-[kitchen['lat'].iloc[6]]*len(customer))**2)
In [7]:
a = pd.DataFrame(np.sort(customer1[['dist0','dist1','dist2','dist3','dist4','dist5','dist6']].values)[:,:6], columns=['nearest','2nearest', '3nearest','4nearest','5nearest','6nearest'])
#a = pd.DataFrame(np.sort(customer1[['dist0','dist1','dist2','dist3','dist4','dist5']].values)[:,:5], columns=['nearest','2nearest', '3nearest','4nearest','5nearest'])
customer1 = customer1.join(a)
customer1.head()
Out[7]:
In [8]:
print(kitchen1)
In [9]:
# Find distance from customer point to central customer point
#customer1['distSort'] = Distance(customer1['lat'].tolist(),customer1['long'].tolist(),[lat_centroid]*len(customer),[lat_centroid]*len(customer))
customer1['distSort'] = 111*np.sqrt( (customer.long-long_centroid)**2 + (customer.lat-lat_centroid)**2)
# Sort by longest distance
customer1 = customer1.sort_values(['distSort'], ascending=False)
In [10]:
customer1.reset_index(drop=True, inplace=True)
df1 = customer1.head(round(len(customer)*10/10))
df2 = customer1.tail(round(len(customer)*0/10))
customer1.drop(customer1.head(round(len(customer)*10/10)).index, inplace=True)
customer1.drop(customer1.tail(round(len(customer)*0/10)).index, inplace=True)
df2 = df2.append(df1,ignore_index=True)
df2 = df2.append(customer1,ignore_index=True)
customer1 = df2
In [11]:
# Data already sorted from (almost) outermost customer
# For each row in the column,assign customer to the the nearest kitchen,
# if the kitchen already full, assign customer to the second nearest kitchen and so on.
# IF MAGIC
clusters = []
dis2clusters = []
#masih manual
cap0 = 0
cap1 = 0
cap2 = 0
cap3 = 0
cap4 = 0
cap5 = 0
cap6 = 0
dis2cluster = 0
for i in customer1.index:
# Nearest
if (customer1['nearest'].loc[i]==customer1['dist0'].loc[i]) and (cap0<100):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif customer1['nearest'].loc[i]==customer1['dist1'].loc[i] and (cap1<40):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif customer1['nearest'].loc[i]==customer1['dist2'].loc[i] and (cap2<60):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif customer1['nearest'].loc[i]==customer1['dist3'].loc[i] and (cap3<70):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif customer1['nearest'].loc[i]==customer1['dist4'].loc[i] and (cap4<80):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif customer1['nearest'].loc[i]==customer1['dist5'].loc[i] and (cap5<50):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif customer1['nearest'].loc[i]==customer1['dist6'].loc[i] and (cap6<50):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
# 2nd Nearest
elif (customer1['2nearest'].loc[i]==customer1['dist0'].loc[i]) and (cap0<100):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif customer1['2nearest'].loc[i]==customer1['dist1'].loc[i] and (cap1<40):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif customer1['2nearest'].loc[i]==customer1['dist2'].loc[i] and (cap2<60):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif customer1['2nearest'].loc[i]==customer1['dist3'].loc[i] and (cap3<70):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif customer1['2nearest'].loc[i]==customer1['dist4'].loc[i] and (cap4<80):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif customer1['2nearest'].loc[i]==customer1['dist5'].loc[i] and (cap5<50):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif customer1['2nearest'].loc[i]==customer1['dist6'].loc[i] and (cap6<50):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
# 3rd Nearest
elif (customer1['3nearest'].loc[i]==customer1['dist0'].loc[i]) and (cap0<100):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif customer1['3nearest'].loc[i]==customer1['dist1'].loc[i] and (cap1<40):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif customer1['3nearest'].loc[i]==customer1['dist2'].loc[i] and (cap2<60):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif customer1['3nearest'].loc[i]==customer1['dist3'].loc[i] and (cap3<70):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif customer1['3nearest'].loc[i]==customer1['dist4'].loc[i] and (cap4<80):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif customer1['3nearest'].loc[i]==customer1['dist5'].loc[i] and (cap5<50):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif customer1['3nearest'].loc[i]==customer1['dist6'].loc[i] and (cap6<50):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
# 4th Nearest
elif (customer1['4nearest'].loc[i]==customer1['dist0'].loc[i]) and (cap0<100):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif customer1['4nearest'].loc[i]==customer1['dist1'].loc[i] and (cap1<40):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif customer1['4nearest'].loc[i]==customer1['dist2'].loc[i] and (cap2<60):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif customer1['4nearest'].loc[i]==customer1['dist3'].loc[i] and (cap3<70):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif customer1['4nearest'].loc[i]==customer1['dist4'].loc[i] and (cap4<80):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif customer1['4nearest'].loc[i]==customer1['dist5'].loc[i] and (cap5<50):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif customer1['4nearest'].loc[i]==customer1['dist6'].loc[i] and (cap6<50):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
# 5th Nearest
elif (customer1['5nearest'].loc[i]==customer1['dist0'].loc[i]) and (cap0<100):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif customer1['5nearest'].loc[i]==customer1['dist1'].loc[i] and (cap1<40):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif customer1['5nearest'].loc[i]==customer1['dist2'].loc[i] and (cap2<60):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif customer1['5nearest'].loc[i]==customer1['dist3'].loc[i] and (cap3<70):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif customer1['5nearest'].loc[i]==customer1['dist4'].loc[i] and (cap4<80):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif customer1['5nearest'].loc[i]==customer1['dist5'].loc[i] and (cap5<50):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif customer1['5nearest'].loc[i]==customer1['dist6'].loc[i] and (cap6<50):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
# 6th Nearest
elif (customer1['6nearest'].loc[i]==customer1['dist0'].loc[i]) and (cap0<100):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif customer1['6nearest'].loc[i]==customer1['dist1'].loc[i] and (cap1<40):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif customer1['6nearest'].loc[i]==customer1['dist2'].loc[i] and (cap2<60):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif customer1['6nearest'].loc[i]==customer1['dist3'].loc[i] and (cap3<70):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif customer1['6nearest'].loc[i]==customer1['dist4'].loc[i] and (cap4<80):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif customer1['6nearest'].loc[i]==customer1['dist5'].loc[i] and (cap5<50):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif customer1['6nearest'].loc[i]==customer1['dist6'].loc[i] and (cap6<50):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
# sisa
elif (cap0+customer1['qtyOrdered'].loc[i]<105):
cluster=0
cap0=cap0+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist0'].loc[i]
elif (cap1+customer1['qtyOrdered'].loc[i]<45):
cluster=1
cap1=cap1+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist1'].loc[i]
elif (cap2+customer1['qtyOrdered'].loc[i]<65):
cluster=2
cap2=cap2+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist2'].loc[i]
elif (cap3+customer1['qtyOrdered'].loc[i]<75):
cluster=3
cap3=cap3+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist3'].loc[i]
elif (cap4+customer1['qtyOrdered'].loc[i]<85):
cluster=4
cap4=cap4+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist4'].loc[i]
elif (cap5+customer1['qtyOrdered'].loc[i]<55):
cluster=5
cap5=cap5+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist5'].loc[i]
elif (cap6+customer1['qtyOrdered'].loc[i]<55):
cluster=6
cap6=cap6+customer1['qtyOrdered'].loc[i]
dis2cluster = customer1['dist6'].loc[i]
clusters.append(cluster)
dis2clusters.append(dis2cluster)
customer1['cluster'] = clusters
customer1['distance2cluster'] = dis2clusters
In [12]:
p = figure(title="Persebaran Customer dan Kitchen",match_aspect=True, aspect_scale=1,plot_width=900)
p.grid.grid_line_color = None
p.background_fill_color = "#eeeeee"
#p.axis.visible = False
mscatter(p, customer1['long'].loc[customer1['cluster'] == 0], customer1['lat'].loc[customer1['cluster'] == 0], "circle", "#1f77b4") # blue dark
mscatter(p, customer1['long'].loc[customer1['cluster'] == 1], customer1['lat'].loc[customer1['cluster'] == 1], "circle", "#aec7e8") # blue light
mscatter(p, customer1['long'].loc[customer1['cluster'] == 2], customer1['lat'].loc[customer1['cluster'] == 2], "circle", "#ff7f0e") # orange dark
mscatter(p, customer1['long'].loc[customer1['cluster'] == 3], customer1['lat'].loc[customer1['cluster'] == 3], "circle", "#ffbb78") # orange light
mscatter(p, customer1['long'].loc[customer1['cluster'] == 4], customer1['lat'].loc[customer1['cluster'] == 4], "circle", "#2ca02c") # green dark
mscatter(p, customer1['long'].loc[customer1['cluster'] == 5], customer1['lat'].loc[customer1['cluster'] == 5], "circle", "#98df8a") # green light
mscatter(p, customer1['long'].loc[customer1['cluster'] == 6], customer1['lat'].loc[customer1['cluster'] == 6], "circle", "#d62728") # red
#mscatter(p, customer1['long'], customer1['lat'], "circle", "red")
mscatter(p, kitchen['long'], kitchen['lat'], "square", "white")
mtext(p, kitchen['long'], kitchen['lat'],["Dapur Miji","Dapur Nusantara","Familia Catering","Pondok Catering","Rose Catering","Tiga Kitchen Catering","Ummu Uwais"])
show(p)
In [13]:
# Count customer order assigned to Kitchen
dapurMiji = (customer1.where(customer1['cluster'] == 0))['qtyOrdered'].sum()
dapurNusantara = (customer1.where(customer1['cluster'] == 1))['qtyOrdered'].sum()
familiaCatering = (customer1.where(customer1['cluster'] == 2))['qtyOrdered'].sum()
pondokRawon = (customer1.where(customer1['cluster'] == 3))['qtyOrdered'].sum()
roseCatering = (customer1.where(customer1['cluster'] == 4))['qtyOrdered'].sum()
tigaKitchenCatering = (customer1.where(customer1['cluster'] == 5))['qtyOrdered'].sum()
ummuUwais = (customer1.where(customer1['cluster'] == 6))['qtyOrdered'].sum()
d = {'Dapur Miji': dapurMiji , 'Dapur Nusantara': dapurNusantara, 'Familia Catering': familiaCatering, 'Pondok Rawon': pondokRawon,'Rose Catering': roseCatering, 'Tiga Kitchen Catering': tigaKitchenCatering, 'Ummu Uwais': ummuUwais}
In [14]:
# Print sum of assigned
# Cek apakah memenuhi constraint
print(d,"\n")
print("Cek apakah jumlah order sesuai :")
print(customer1['qtyOrdered'].sum()," pada data input")
print(cap0+cap1+cap2+cap3+cap4+cap5+cap6," pada hasil assign")
In [15]:
print(kitchen1)
In [16]:
customer1.drop(['distSort','dist0', 'dist1', 'dist2','dist3','dist4','dist5','dist6','nearest','2nearest','3nearest','4nearest','5nearest','6nearest'],axis=1, inplace=True)
In [17]:
# Get degree for each customer in the cluster
def getDegree(data):
# distance
# center long lat (start of routing)
degrees = []
degree = 0
for i in data.index:
if data['cluster'].loc[i]==0:
center_latitude = kitchen['lat'].iloc[0]
center_longitude = kitchen['long'].iloc[0]
elif data['cluster'].loc[i]==1:
center_latitude = kitchen['lat'].iloc[1]
center_longitude = kitchen['long'].iloc[1]
elif data['cluster'].loc[i]==2:
center_latitude = kitchen['lat'].iloc[2]
center_longitude = kitchen['long'].iloc[2]
elif data['cluster'].loc[i]==3:
center_latitude = kitchen['lat'].iloc[3]
center_longitude = kitchen['long'].iloc[3]
elif data['cluster'].loc[i]==4:
center_latitude = kitchen['lat'].iloc[4]
center_longitude = kitchen['long'].iloc[4]
elif data['cluster'].loc[i]==5:
center_latitude = kitchen['lat'].iloc[5]
center_longitude = kitchen['long'].iloc[5]
elif data['cluster'].loc[i]==6:
center_latitude = kitchen['lat'].iloc[6]
center_longitude = kitchen['long'].iloc[6]
degree = np.rint(np.rad2deg(np.arctan2((data['lat'].loc[i]-center_latitude),(data['long'].loc[i]-center_longitude))))
degrees.append(degree)
# For each row in the column,
data['degrees'] = degrees
return data
getDegree(customer1)
customer1.head()
Out[17]:
Kenapa dilihat derajat, karena kalo dari jarak saja, misal diambil paling dekat pasti kurir awal selesai cepat karena dekat dan kurir akhir lama karena dapat sisa yang jauh jauh. Dengan melihat derajat nya terlebih dahulu kelemahan itu bisa dikurangi dan sedikit meratakan beban kurir.
In [18]:
# Assign kurir dari kitchen ke customer berdasarkan degree dan jarak
# Priority utama berdasarkan degree jadi gaada kurir yang deket doang
# Tapi belum dipikir gimana bisa optimize waktu harus satu jam max, tapi seenggaknya kurir udah agak rata jaraknya
# Kasus khusus apabila yg degree nya kecil jaraknya jauh banget, dia kurir baru.
customer1 = customer1.sort_values(['cluster','degrees','distance2cluster'], ascending=[True,True,True])
customer1.reset_index(drop=True, inplace=True)
customer1.head()
Out[18]:
In [19]:
kurirs = []
kurir = 1
sum = 0
dis = 0
kurirDist = []
# Estimasi kecepatan rata2 di jakata 22kmph -> http://www.viva.co.id/blog/entertainment/336836-kecepatan-rata-rata-motor-di-jakarta-22-kpj
for i in customer1.index:
if customer1['cluster'].loc[i]==0:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
if customer1['cluster'].loc[i]==1:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
if customer1['cluster'].loc[i]==2:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
if customer1['cluster'].loc[i]==3:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
if customer1['cluster'].loc[i]==4:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
if customer1['cluster'].loc[i]==5:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
if customer1['cluster'].loc[i]==6:
if sum+customer1['qtyOrdered'].loc[i]<=40:
sum=sum+customer1['qtyOrdered'].loc[i]
elif sum+customer1['qtyOrdered'].loc[i]>40:
kurir=kurir+1
sum=0
dis=0
if dis>20:
kurir=kurir+1
sum=0
dis=0
if dis==0:
dis=dis+customer1['distance2cluster'].loc[i]
else:
dis=dis+111*np.sqrt( (customer1['long'].loc[i]-customer1['long'].loc[i-1])**2 + (customer1['lat'].loc[i]-customer1['lat'].loc[i-1])**2)
kurirDist.append(dis)
kurirs.append(kurir)
customer1['kurir'] = kurirs
customer1['kurirDist'] = kurirDist
In [20]:
print("Jumlah Kurir :",customer1['kurir'].max())
print("Rata-Rata Bawaan Kurir",(customer1.groupby(['kurir'])['qtyOrdered'].sum()).mean())
print("Rata-Rata Distance Kurir",(customer1.groupby(['kurir'])['kurirDist'].max()).mean())
print("Biaya Pengiriman per hari")
print("Lower Bound :",customer1['kurir'].max()*25000) # Tepat Waktu
print("Upper Bound :",customer1['kurir'].max()*25000*3) # 3 Jam
In [21]:
# Jumlah titik pengiriman tiap kurir
customer1.groupby(['kurir'])['customersName'].count()
Out[21]:
In [22]:
# Bawaan setiap kurir
customer1.groupby(['kurir'])['qtyOrdered'].agg('sum')
Out[22]:
In [23]:
# Distance per kurir
customer1.groupby(['kurir'])['kurirDist'].max()
Out[23]:
In [24]:
# Data visulization customer assigned to its kitchen
def visualize(data):
x = data['long']
y = data['lat']
Cluster = data['kurir']
cm = plt.cm.get_cmap('tab20c')
fig = plt.figure()
ax = fig.add_subplot(111)
scatter = ax.scatter(x,y,c=Cluster, cmap=cm, s=10, label='customer')
ax.scatter(kitchen['long'],kitchen['lat'], s=10, c='r', marker="x", label='second')
ax.set_xlabel('longitude')
ax.set_ylabel('latitude')
plt.colorbar(scatter)
fig.show()
visualize(customer1)
-Grup customer dan kitchen belum optimum, masih ada outlier karena algoritma tidak sempurna
-Waktu tempuh pengiriman untuk memenuhi constraint hanya estimasi. Asumsi rata-rata 22kmpj, driver di limit 20-25 km.
http://www.viva.co.id/blog/entertainment/336836-kecepatan-rata-rata-motor-di-jakarta-22-kpj
-Tidak memperhitungkan waktu drop off (Berapa lama berhenti setiap pada tiap customer)
-Ada kurir yang mengantar ke cluster yang berbeda (jauh) karena pesanannya tanggung
-Belum ada mekanisme drop kitchen
In [25]:
customer1.drop(['degrees'],axis=1, inplace=True)
customer1.to_csv("result.csv", sep=',', encoding='utf-8')
In [26]:
customer1.head()
Out[26]:
Big Thanks
-anaconda https://anaconda.org/
-jupyter notebook http://jupyter.org/
-numpy http://www.numpy.org/
-pandas http://pandas.pydata.org/
-bokeh https://bokeh.pydata.org/en/latest/
-matplotlib https://matplotlib.org/
In [ ]: