回国后,没有时间休息,一是工作不能耽误,二是很多杂乱的事情要处理,因此,公众号很久没有更新,实在抱歉!
本期的推文是关于旅行商问题(TSP)的配送网络优化,也是因为最近在指导学生参加省大学生现代物流设计大赛,才有此推文。在此,我要特别感谢我指导的学生!
一、问题描述
云通物流配送中心要配货至8个步步高门店,设计一条运输费用最低的配送路线。各节点地理坐标如下表所示:
显然,配送路线的优化要考虑很多因素,本期只简单的运用旅行商问题(TSP)进行优化设计。
library(knitr)
library(dplyr)
library(ggplot2)
#9个节点
n
#各节点间的经度和纬度最大值
#from 0 to ...
max_x
max_y
#设置随机种子,便于结果重现
set.seed(20201130)
#读取各节点原始数据
codes
#各节点散点图展示
ggplot(codes,aes(x, y)) + geom_point()
#计算各节点距离
distance
dist_fun
vapply(seq_along(i), function(k)distance[i[k], j[k]], numeric(1L))
}
#基于ompr包构建模型
library(ompr)
model %
#构建节点i到节点j的决策变量
add_variable(x[i, j], i = 1:n, j = 1:n,
type = "integer", lb =0, ub = 1) %>%
# a helper variable for the MTZ formulationof the tsp
add_variable(u[i], i = 1:n, lb = 1, ub = n)%>%
# minimize travel distance
set_objective(sum_expr(dist_fun(i, j) *x[i, j], i = 1:n, j = 1:n), "min") %>%
# 配送路线不能走相同的节点
set_bounds(x[i, i], ub = 0, i = 1:n) %>%
# 离开每个节点
add_constraint(sum_expr(x[i, j], j = 1:n) ==1, i = 1:n) %>%
# 到达每个节点
add_constraint(sum_expr(x[i, j], i = 1:n) ==1, j = 1:n) %>%
#确保没有子汇总(弧约束)
add_constraint(u[i] >= 2, i = 2:n) %>%
add_constraint(u[i] - u[j] + 1 <= (n - 1)* (1 - x[i, j]), i = 2:n, j = 2:n)
model
#计算结果如下
#我们使用GPLK算法计算该混合整数规划问题
library(ompr.roi)
library(ROI.plugin.glpk)
result
result
#Status: optimal
#Objective value: 25.79845
solution %
filter(value > 0)
kable(head(solution, 9))
#配送路线如下
#将各配送节点连接并可视化
paths %
rename(from = i, to = j) %>%
mutate(trip_id = row_number()) %>%
tidyr::gather(property, idx_val, from:to) %>%
mutate(idx_val = as.integer(idx_val)) %>%
inner_join(codes, by = c("idx_val" = "id"))
kable(head(arrange(paths, trip_id), 6))
#结果
ggplot(codes, aes(x, y)) +
geom_point() +
geom_line(data = paths, aes(group = trip_id)) +
ggtitle(paste0("Optimal route with cost: ",round(objective_value(result), 2)))
参考文献:
Michael Hahsler&KurtHornik.TSP Infrastructure for the Traveling Salesperson Problem,Journal of StatisticalSoftware, 2007(12).