场景设置:单出发点多到达点,每个小时的固定时间发车
第一步:模拟一个地区的出行需求,这里设置500个订单需求点(经纬度)并随机分配给各个小时(7到22点)。将这些点聚类,聚类结果设置为定制公交下车点。
下二步预告:根据下车点间距离生成下车顺序,使得总里程最短,设置订单需求的退票率。
优化方向:下车点选择和顺序确定?票价的确定使得总利润最大?设置权重?其实还没想好,如果有大佬看到还望不吝赐教~
# 导入所需包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import random
import math
from sklearn.cluster import KMeans
# 随机生成500个初始需求及所在位置、需求时间
def generate_random_gps(base_log=None, base_lat=None, radius=None):
radius_in_degrees = radius / 111300
u = float(random.uniform(0.0, 1.0))
v = float(random.uniform(0.0, 1.0))
w = radius_in_degrees * math.sqrt(u)
t = 2 * math.pi * v
x = w * math.cos(t)
y = w * math.sin(t)
longitude = y + base_log
latitude = x + base_lat
return longitude, latitude
c_lon = list()
c_lat = list()
c_hour=list()
for i in range(500):
lon, lat = generate_random_gps(base_log=120, base_lat=30, radius=100000) # 基准点经纬度和距离基准点的半径
hour=random.randint(7, 22)
c_lon.append(lon)
c_lat.append(lat)
c_hour.append(hour)
# random.random()
dict = {'lon':c_lon,'lat':c_lat,'hour':c_hour}
df_ini= pd.DataFrame(dict)
df_ini.sort_values(by='hour',inplace=True)
def kmeans():
df = df_ini[df_ini.hour == 7].reset_index(drop=True)
feature_location = df[['lon', 'lat']]
kmean = KMeans(n_clusters=3) # 三个下车点
km = kmean.fit(feature_location)
df['cluster'] = km.labels_
centers = df.groupby("cluster").mean().reset_index()
for i in range(8,23): # 每小时聚类一次
df = df_ini[df_ini.hour == i].reset_index(drop=True)
feature_location = df[['lon', 'lat']]
kmean = KMeans(n_clusters=3) # 三个下车点
km = kmean.fit(feature_location)
df['cluster'] = km.labels_
center_s = df.groupby("cluster").mean().reset_index() # 下车点位置
centers=pd.concat([centers, center_s],axis=0).reset_index(drop=True)
# 画图
'''df1 = df[df.cluster == 0].reset_index(drop=True)
x = df1['lon']
y = df1['lat']
df2 = df[df.cluster == 1].reset_index(drop=True)
x1 = df2['lon']
y1 = df2['lat']
df3 = df[df.cluster == 2].reset_index(drop=True)
x2 = df3['lon']
y2 = df3['lat']
ax1 = plt.axes()
ax1.scatter(x, y)
ax1.scatter(x1, y1, color='red')
ax1.scatter(x2, y2, color='green')
plt.show()'''
print(centers)
if __name__ == "__main__":
kmeans()