得到最优结果得到速度太慢优化一下%% 基础数据加载
node_coords = [
12041.7252, 3892.7009
12051.7044, 3899.4222
12051.4094, 3897.3103
12046.3461, 3904.73
]; % 配送节点坐标
customer_data = xlsread('新建 Microsoft Excel 工作表.xlsx', 'Sheet1');
customer_coords = customer_data(:, 1:2); % 客户坐标
delivery_demand = customer_data(:,3); % 正向配送需求
recycle_demand = customer_data(:,4); % 逆向回收需求
%% 参数设置
max_distance = 400; % 单程最大距离(km)
vehicle_speed = 50; % 车速(km/h)
vehicle_capacity = 10; % 单车运载量
depot_capacity = 10000; % 节点服务能力
operating_cost = 400; % 节点运营成本
cr1 = 300; % 车辆租赁成本
c0 = 200; % 车辆启动成本
c1 = 0.64; % 载重运输成本系数(元/吨·公里)
c2 = 1.96; % 空车行驶成本系数(元/公里)
%% 距离矩阵生成
all_points = [node_coords; customer_coords];
distance_matrix = squareform(pdist(all_points, 'euclidean'));
known_solution.node1 = [4, 6, 10, 14, 21, 27, 34, 39, 49, 51, 53, 59, 76, 78, 82, 99, 105, 123, 126, 127,129, 133, 134, 160];
known_solution.node2 = [8, 11, 17, 23, 31, 32, 36, 42, 43, 45, 54, 55, 58, 61, 67, 74, 83, 84, 85, 87,90, 91, 100, 103, 106, 113, 116, 118, 124, 136, 137, 138, 139, 140, 141, 142, 143, 144, 149, 150,151, 161];
known_solution.node3 = [3, 7, 9, 16, 18, 20, 28, 29, 30, 33, 40, 44, 47, 50, 56, 57, 62, 64, 66, 69,79, 81, 92, 93, 94, 97, 101, 102, 104, 111, 114, 115, 119, 122, 128, 130, 132, 152, 153, 154,155, 158, 159];
known_solution.node4 = [1, 2, 5, 12, 13, 15, 19, 22, 24, 25, 26, 35, 37, 38, 41, 46, 48, 52, 60, 63,65, 68, 70, 71, 72, 73, 75, 77, 80, 86, 88, 89, 95, 96, 98, 107, 108, 109, 110, 112,117, 120, 121, 125, 131, 135, 145, 146, 147, 148, 156, 157, 162, 163];
%% 遗传算法参数
pop_size = 50; % 种群数量
max_gen = 100; % 最大迭代次数
cross_rate = 0.85; % 交叉概率
mutate_rate = 0.1; % 变异概率
elite_percentage = 0.05; % 新增
elite_size = max(2, round(pop_size * elite_percentage)); % 新增
%% 染色体编码函数
function chrom = createChrom(nodes_num, customers_num, known_solution)
if nargin > 2 && ~isempty(known_solution)
% 从已知方案构建染色体
alloc_vec = zeros(1, customers_num);
seq_vec = zeros(1, customers_num);
% 分配部分编码
alloc_vec(known_solution.node1) = 1;
alloc_vec(known_solution.node2) = 2;
alloc_vec(known_solution.node3) = 3;
alloc_vec(known_solution.node4) = 4;
% 顺序部分编码 (保持客户在原始列表中的顺序)
seq_vec = [known_solution.node1, known_solution.node2, known_solution.node3, known_solution.node4];
chrom = [alloc_vec, seq_vec];
else
% 随机初始化
allocation = randi(nodes_num, 1, customers_num);
sequence = randperm(customers_num);
chrom = [allocation, sequence];
end
end
%% 适应度函数
function [total_cost] = fitnessFunc(chrom, distance_matrix, params)
nodes_num = size(params.node_coords,1);
customers_num = length(params.customer_coords);
allocation = chrom(1:customers_num);
global_sequence = chrom(customers_num+1:end);
total_cost = 0;
for n = 1:nodes_num
% 获取当前节点的所有客户
node_customers = find(allocation == n);
% 无客户分配到当前节点时的处理
if isempty(node_customers)
continue;
end
% 从全局序列中提取分配给当前节点的客户(保持原始顺序)
route_order = global_sequence(ismember(global_sequence, node_customers));
% 节点容量检查
node_delivery = sum(params.delivery_demand(route_order));
node_recycle = sum(params.recycle_demand(route_order));
if node_delivery > params.depot_capacity
total_cost = total_cost + 1e6; % 大容量惩罚
continue;
end
% 路径分割与成本计算
vehicle_routes = baseSplitRoutes(route_order, n, params, distance_matrix);
vehicle_count = length(vehicle_routes);
% 计算运输成本
for r = 1:vehicle_count
route = vehicle_routes{r};
transport_cost = calculateSegmentCost(route, n, params, distance_matrix);
total_cost = total_cost + transport_cost;
end
% 累加固定成本
total_cost = total_cost + params.operating_cost + ...
vehicle_count * (params.cr1 + params.c0);
end
end
figure('Name','适应度进化曲线','NumberTitle','off');
h_plot = plot(0, 0, 'b-', 0, 0, 'r--');
title('适应度进化过程');
xlabel('迭代代数');
ylabel('适应度值');
legend('最佳适应度', '平均适应度');
grid on;
hold on;
% 初始化存储数组
best_history = zeros(max_gen,1);
avg_history = zeros(max_gen,1);
%% 遗传算法主循环
population = arrayfun(@(x) createChrom(size(node_coords,1), size(customer_coords,1)),...
1:pop_size, 'UniformOutput', false);
best_cost = Inf;
adaptive_params = struct(...
'cross_rate', 0.85,... % 初始交叉率
'mutate_rate', 0.15,... % 初始变异率
'stagnation', 0); % 停滞计数器
for gen = 1:max_gen
% 计算适应度
%% 修改后的适应度函数调用(添加max_distance字段)
costs = cellfun(@(x) fitnessFunc(x, distance_matrix, struct(...
'node_coords', node_coords,...
'customer_coords', customer_coords,...
'delivery_demand', delivery_demand,...
'recycle_demand', recycle_demand,...
'depot_capacity', depot_capacity,...
'vehicle_capacity', vehicle_capacity,...
'max_distance', max_distance,... % 新增字段
'operating_cost', operating_cost,...
'cr1', cr1,...
'c0', c0,...
'c1', c1,...
'c2', c2)),...
population);
[min_cost, idx] = min(costs);
current_avg = mean(costs);
best_history(gen) = min_cost;
avg_history(gen) = current_avg;
% 更新可视化曲线
set(h_plot(1), 'XData', 1:gen, 'YData', best_history(1:gen));
set(h_plot(2), 'XData', 1:gen, 'YData', avg_history(1:gen));
xlim([1 max_gen]);
drawnow;
if min_cost < best_cost
best_solution = population{idx};
best_cost = min_cost;
end
[sorted_costs, sort_idx] = sort(costs);
elite_pop = population(sort_idx(1:elite_size));
% 选择操作
select_size = pop_size - elite_size;
selected_pop = tournamentSelection(population, costs, 3, select_size);
% 交叉操作
new_population = cell(1, select_size);
num_pairs = floor(select_size/2); % 计算完整配对数
% 处理成对交叉
for i = 1:num_pairs
idx1 = 2*i-1; % 第一个个体索引
idx2 = 2*i; % 第二个个体索引
parent1 = selected_pop{idx1};
parent2 = selected_pop{idx2};
if rand() < cross_rate
[child1, child2] = depotCrossover(parent1, parent2, size(customer_coords,1));
new_population{idx1} = child1;
new_population{idx2} = child2;
else
new_population{idx1} = parent1;
new_population{idx2} = parent2;
end
end
% 处理奇数情况的剩余个体
if mod(select_size, 2) == 1
last_idx = select_size;
if rand() < mutate_rate % 当种群为奇数时,最后一个个体变异概率增加
new_population{last_idx} = depotMutate(selected_pop{last_idx},...
size(node_coords,1),...
size(customer_coords,1));
else
new_population{last_idx} = selected_pop{last_idx};
end
end
% 变异操作
for i = 1:select_size
if rand() < mutate_rate
new_population{i} = depotMutate(new_population{i},...
size(node_coords,1),...
size(customer_coords,1));
end
end
if gen > 20 && std(costs) < 0.1*mean(costs)
adaptive_params.cross_rate = min(0.95, adaptive_params.cross_rate + 0.05);
adaptive_params.mutate_rate = min(0.3, adaptive_params.mutate_rate + 0.02);
else
adaptive_params.cross_rate = 0.85;
adaptive_params.mutate_rate = 0.15;
end
% 使用调整后的参数
cross_rate = adaptive_params.cross_rate;
mutate_rate = adaptive_params.mutate_rate;
population = [elite_pop, new_population];
end
%% 结果显示
disp(['最优成本:' num2str(best_cost)]);
visualizeRoutes(best_solution, node_coords, customer_coords);
%% 修正后的可视化函数(分拆为两个独立函数)
function visualizeRoutes(chrom, depot_coords, customer_coords)
% 整体路径可视化函数
num_customers = length(customer_coords);
num_depots = size(depot_coords,1);
figure;
hold on;
% 绘制仓库
scatter(depot_coords(:,1), depot_coords(:,2), 100, 'k^', 'filled');
% 绘制客户点
scatter(customer_coords(:,1), customer_coords(:,2), 50, 'bo');
% 解析路径
for d = 1:num_depots
depot_customers = find(chrom(1:num_customers) == d);
if ~isempty(depot_customers)
[~, seq_pos] = ismember(depot_customers, chrom(num_customers+1:end));
valid_seq = seq_pos(seq_pos > 0);
[~, order] = sort(valid_seq);
sorted_customers = depot_customers(order);
route = [depot_coords(d,:);
customer_coords(sorted_customers,:);
depot_coords(d,:)];
plot(route(:,1), route(:,2), 'LineWidth', 1.5);
end
end
hold off;
title('全局配送路径');
xlabel('X坐标');
ylabel('Y坐标');
legend('仓库', '客户点');
end
function visualizeDepotRoutes(chrom, depot_coords, customer_coords)
% 各节点独立路径可视化函数
num_customers = length(customer_coords);
num_depots = size(depot_coords,1);
for d = 1:num_depots
figure('Position', [200+(d-1)*50, 200+(d-1)*50, 600, 400]);
hold on;
title(['配送中心' num2str(d) '路径规划']);
% 绘制当前配送中心
scatter(depot_coords(d,1), depot_coords(d,2), 150, 'r^', 'filled');
depot_customers = find(chrom(1:num_customers) == d);
if ~isempty(depot_customers)
[~, seq_pos] = ismember(depot_customers, chrom(num_customers+1:end));
valid_seq = seq_pos(seq_pos > 0 & seq_pos <= length(chrom)-num_customers);
[~, order] = sort(valid_seq);
sorted_customers = depot_customers(order);
% 客户点标注
scatter(customer_coords(sorted_customers,1),...
customer_coords(sorted_customers,2),...
80, 'bo', 'filled');
text_offset = 0.1 * max(range(customer_coords));
text(customer_coords(sorted_customers,1)+text_offset,...
customer_coords(sorted_customers,2)+text_offset,...
cellstr(num2str(sorted_customers')),...
'FontSize',8);
% 路径绘制
route = [depot_coords(d,:);
customer_coords(sorted_customers,:);
depot_coords(d,:)];
plot(route(:,1), route(:,2), 'b--o',...
'LineWidth',1.5,...
'MarkerSize',6,...
'MarkerFaceColor','w');
else
text(mean(depot_coords(d,1)), mean(depot_coords(d,2)),...
'无服务客户',...
'HorizontalAlignment','center',...
'FontSize',12);
end
xlabel('X坐标 (米)');
ylabel('Y坐标 (米)');
grid on;
axis equal;
hold off;
end
end
%% 交叉操作函数实现
function [child1, child2] = depotCrossover(parent1, parent2, num_customers)
% 分配部分交叉(均匀交叉)
alloc_part1 = parent1(1:num_customers);
alloc_part2 = parent2(1:num_customers);
mask = randi([0 1], 1, num_customers);
child1_alloc = alloc_part1.*mask + alloc_part2.*(~mask);
child2_alloc = alloc_part1.*(~mask) + alloc_part2.*mask;
% 路径顺序交叉(OX交叉)
seq_part1 = parent1(num_customers+1:end);
seq_part2 = parent2(num_customers+1:end);
[child1_seq, child2_seq] = oxCrossover(seq_part1, seq_part2);
child1 = [child1_alloc, child1_seq];
child2 = [child2_alloc, child2_seq];
end
%% 修正后的OX交叉辅助函数
function [child1, child2] = oxCrossover(parent1, parent2)
n = length(parent1);
cp = sort(randi(n-1,1,2)); % 确保交叉点有效
if cp(1) == cp(2), cp(2) = cp(2)+1; end % 防止相同切点
% 子代1生成
segment = parent1(cp(1):cp(2));
remaining = parent2(~ismember(parent2, segment));
child1 = [remaining(1:cp(1)-1), segment, remaining(cp(1):end)];
% 子代2生成(修正索引错误)
segment = parent2(cp(1):cp(2));
remaining = parent1(~ismember(parent1, segment));
% 确保索引不越界
if (cp(1)-1) <= length(remaining)
part1 = remaining(1:cp(1)-1);
else
part1 = remaining(1:end);
end
child2 = [part1, segment, remaining(cp(1):end)];
end
%% 变异操作函数实现
function mutated = depotMutate(chrom, num_depots, num_customers)
if rand() < 0.5
% 分配变异:随机改变一个客户的分配
pos = randi(num_customers);
new_depot = randi(num_depots);
mutated = chrom;
mutated(pos) = new_depot;
else
% 路径顺序变异:交换两个位置
seq = chrom(num_customers+1:end);
swap_pos = randperm(num_customers, 2);
seq(swap_pos) = seq(fliplr(swap_pos));
mutated = [chrom(1:num_customers), seq];
end
end
%% 历史最优成本可视化
% 生成累积最优成本数组
cumulative_min = cummin(best_history);
figure('Color','w');
plot(cumulative_min, 'b-',...
'LineWidth',1.2,...
'MarkerSize',4,...
'MarkerFaceColor','w');
% 设置坐标轴标签
xlabel('迭代代数');
ylabel('历史最优成本 (万元)');
title('全局最优成本进化过程');
% 自动标注最终最优值
[final_min, final_gen] = min(cumulative_min);
text(final_gen, final_min,...
sprintf(' %.2f万 @%d代', final_min/10000, final_gen),...
'VerticalAlignment','bottom',...
'FontSize',9);
% 智能坐标轴设置
ax = gca;
ax.YAxis.Exponent = floor(log10(final_min)) - 1; % 自动确定指数
grid on;
%% 新增的运输成本计算函数
function cost = calculateRouteCost(route, params, distance_matrix)
num_nodes = size(params.node_coords,1);
depot_id = mode(params.chrom(route)); % 获取所属配送中心
% 正向运输成本
forward_cost = 0;
current_load = sum(params.delivery_demand(route));
% 配送中心到第一个客户
from = depot_id;
to = route(1) + num_nodes;
distance = distance_matrix(from, to);
forward_cost = forward_cost + (params.c1*current_load + params.c2)*distance;
% 客户间运输
for k = 2:length(route)
from = route(k-1) + num_nodes;
to = route(k) + num_nodes;
distance = distance_matrix(from, to);
current_load = current_load - params.delivery_demand(route(k-1));
forward_cost = forward_cost + (params.c1*current_load + params.c2)*distance;
end
% 逆向运输成本
recycle_load = sum(params.recycle_demand(route));
from = route(end) + num_nodes;
to = depot_id;
distance = distance_matrix(from, to);
recycle_cost = (params.c1*recycle_load + params.c2)*distance;
cost = forward_cost + recycle_cost;
end
%% 配送方案输出函数
function printDeliveryPlan(best_solution, params, distance_matrix)
num_depots = size(params.node_coords,1);
num_customers = size(params.customer_coords,1);
% 解析染色体
allocation = best_solution(1:num_customers);
global_sequence = best_solution(num_customers+1:end);
% 创建结果结构体
depot_info = struct(...
'DepotID', {},...
'Vehicles', {},...
'TotalCost', {},...
'Details', {});
% 遍历所有配送中心
for depot_id = 1:num_depots
% 获取当前配送中心分配的客户
customers = find(allocation == depot_id);
if isempty(customers)
continue;
end
% 获取路径顺序
[~, seq_pos] = ismember(customers, global_sequence);
valid_seq = seq_pos(seq_pos > 0);
[~, sort_idx] = sort(valid_seq);
route_order = customers(sort_idx);
% 路径分割
vehicle_routes = baseSplitRoutes(route_order, depot_id, params, distance_matrix);
% 计算成本和详细信息
depot_cost = 0;
vehicle_details = cell(length(vehicle_routes),1);
for v = 1:length(vehicle_routes)
route = vehicle_routes{v};
[cost, detail] = calculateVehicleCost(route, depot_id, params, distance_matrix);
vehicle_details{v} = detail;
depot_cost = depot_cost + cost;
end
% 添加固定成本
depot_cost = depot_cost + params.operating_cost + ...
length(vehicle_routes)*(params.cr1 + params.c0);
% 存储结果
depot_info(end+1) = struct(...
'DepotID', depot_id,...
'Vehicles', length(vehicle_routes),...
'TotalCost', depot_cost,...
'Details', {vehicle_details});
end
%% 打印结果
fprintf('========== 全局配送方案 ==========\n');
total_cost = sum([depot_info.TotalCost]);
fprintf('总运营成本: %.2f 万元\n', total_cost/10000);
for d = 1:length(depot_info)
fprintf('\n=== 配送中心%d ===\n', depot_info(d).DepotID);
fprintf('派出车辆: %d\n', depot_info(d).Vehicles);
fprintf('中心总成本: %.2f 万元\n', depot_info(d).TotalCost/10000);
% 打印车辆明细
fprintf('\n车辆明细:\n');
fprintf('%-8s%-12s%-12s%-10s%-10s%-12s%-15s\n',...
'车辆ID','正向载货量','逆向载载量','里程(km)','运输成本','总成本','服务客户顺序');
for v = 1:length(depot_info(d).Details)
detail = depot_info(d).Details{v};
total = detail.transport_cost + params.cr1 + params.c0;
% 生成客户顺序字符串
customer_str = strjoin(arrayfun(@(x) sprintf('%d',x), detail.customers, 'UniformOutput', false),'->');
fprintf('%-8d%-12.2f%-12.2f%-10.2f%-10.2f%-12.2f%-15s\n',...
v,...
detail.delivery_load,...
detail.recycle_load,...
detail.distance,...
detail.transport_cost,...
total,...
customer_str); % 新增客户顺序输出
end
end
end
%% 非递归路径分割函数
function vehicle_routes = baseSplitRoutes(route_order, depot_id, params, distance_matrix)
vehicle_routes = {};
num_nodes = size(params.node_coords,1);
i = 1;
% 预计算所有客户到仓库的距离
depot_distances = distance_matrix(depot_id, num_nodes+1:end);
while i <= length(route_order)
current_load = 0;
current_distance = 0;
segment = [];
% 初始仓库到第一个客户的检查
first_cust = route_order(i);
start_distance = depot_distances(first_cust);
return_distance = distance_matrix(num_nodes+first_cust, depot_id);
for j = i:length(route_order)
cust = route_order(j);
% 新增客户后的载重检查
new_load = current_load + params.delivery_demand(cust) + params.recycle_demand(cust);
% 计算新增客户后的总距离
if isempty(segment)
new_dist = start_distance + return_distance;
else
last_cust = segment(end);
leg1 = distance_matrix(num_nodes+last_cust, num_nodes+cust);
leg2 = distance_matrix(num_nodes+cust, depot_id);
new_dist = current_distance - distance_matrix(num_nodes+last_cust, depot_id)...
+ leg1 + leg2;
end
% 约束条件验证
if new_load > params.vehicle_capacity || new_dist > params.max_distance
break;
end
% 更新当前路径段
segment = [segment, cust];
current_load = new_load;
current_distance = new_dist;
end
if ~isempty(segment)
vehicle_routes{end+1} = segment;
i = i + length(segment);
else
% 处理无法服务的客户
warning('客户%d无法满足约束条件', route_order(i));
i = i + 1;
end
end
end
%% 修正后的车辆成本计算函数
function [total_cost, detail] = calculateVehicleCost(route, depot_id, params, distance_matrix)
num_nodes = size(params.node_coords,1);
% 运输成本计算
transport_cost = 0;
total_distance = 0;
% 仓库到第一个客户
from = depot_id;
to = route(1) + num_nodes;
distance = distance_matrix(from, to);
transport_cost = transport_cost + (params.c1*sum(params.delivery_demand(route)) + params.c2)*distance;
total_distance = total_distance + distance;
% 客户间移动
for k = 2:length(route)
from = route(k-1) + num_nodes;
to = route(k) + num_nodes;
distance = distance_matrix(from, to);
remaining_delivery = sum(params.delivery_demand(route(k:end)));
transport_cost = transport_cost + (params.c1*remaining_delivery + params.c2)*distance;
total_distance = total_distance + distance;
end
% 返回仓库
from = route(end) + num_nodes;
to = depot_id;
distance = distance_matrix(from, to);
transport_cost = transport_cost + (params.c1*sum(params.recycle_demand(route)) + params.c2)*distance;
total_distance = total_distance + distance;
% 修正后的结构体定义(合并字段定义)
detail = struct(...
'customers', route,... % 客户顺序
'delivery_load', sum(params.delivery_demand(route)),...
'recycle_load', sum(params.recycle_demand(route)),...
'distance', total_distance,...
'transport_cost',transport_cost);
total_cost = transport_cost + params.cr1 + params.c0;
end
%% 在主循环后调用输出函数(添加在结果显示部分)
% 结果显示
disp(['最优成本:' num2str(best_cost)]);
visualizeRoutes(best_solution, node_coords, customer_coords);
visualizeDepotRoutes(best_solution, node_coords, customer_coords); % 分节点视图
%% 修改后的printDeliveryPlan调用
printDeliveryPlan(best_solution, struct(...
'node_coords', node_coords,...
'customer_coords', customer_coords,...
'delivery_demand', delivery_demand,...
'recycle_demand', recycle_demand,...
'depot_capacity', depot_capacity,...
'vehicle_capacity', vehicle_capacity,...
'max_distance', max_distance,... % 新增字段
'operating_cost', operating_cost,...
'cr1', cr1,...
'c0', c0,...
'c1', c1,...
'c2', c2), distance_matrix);
function optimized_route = twoOptOptimization(route, distance_matrix, params)
num_nodes = length(route);
improved = true;
best_route = route;
best_cost = calculateRouteCost(route, params, distance_matrix);
while improved
improved = false;
for i = 1:num_nodes-1
for j = i+2:num_nodes
new_route = best_route;
new_route(i+1:j) = new_route(j:-1:i+1);
new_cost = calculateRouteCost(new_route, params, distance_matrix);
if new_cost < best_cost
best_route = new_route;
best_cost = new_cost;
improved = true;
end
end
end
end
optimized_route = best_route;
end
function selected = tournamentSelection(population, fitness, tournament_size, select_size)
pop_size = length(population);
selected = cell(1, select_size);
for i = 1:select_size
candidates = randperm(pop_size, tournament_size);
[~, idx] = min(fitness(candidates)); % 选择适应度最优的个体
selected{i} = population{candidates(idx)};
end
end
function optimized_routes = optimizedSplitRoutes(route_order, depot_id, params, distance_matrix)
% 调用基础函数
raw_routes = baseSplitRoutes(route_order, depot_id, params, distance_matrix);
% 2-opt优化处理
optimized_routes = cellfun(@(x) twoOptOptimization(x, distance_matrix, params),...
raw_routes, 'UniformOutput', false);
end
function transport_cost = calculateSegmentCost(segment, depot_id, params, distance_matrix)
num_nodes = size(params.node_coords,1);
transport_cost = 0;
% 正向运输成本
current_delivery = sum(params.delivery_demand(segment));
% 配送中心到第一个客户
from = depot_id;
to = segment(1) + num_nodes;
distance = distance_matrix(from, to);
transport_cost = transport_cost + (params.c1*current_delivery + params.c2)*distance;
% 客户间运输
for k = 2:length(segment)
from = segment(k-1) + num_nodes;
to = segment(k) + num_nodes;
distance = distance_matrix(from, to);
remaining_delivery = current_delivery - sum(params.delivery_demand(segment(1:k-1)));
transport_cost = transport_cost + (params.c1*remaining_delivery + params.c2)*distance;
end
% 逆向运输成本
recycle_load = sum(params.recycle_demand(segment));
from = segment(end) + num_nodes;
to = depot_id;
distance = distance_matrix(from, to);
transport_cost = transport_cost + (params.c1*recycle_load + params.c2)*distance;
end
function [vehicle_routes, extra_vehicles] = enhancedSplitRoutes(route_order, depot_id, params, distance_matrix)
vehicle_routes = {};
extra_vehicles = struct('customers', {}, 'count', {}, 'cost', {});
i = 1;
while i <= length(route_order)
current_load = 0;
segment = [];
extra_count = 0;
% 逐个客户装载直到容量上限
for j = i:length(route_order)
customer = route_order(j);
new_load = current_load + params.delivery_demand(customer) + params.recycle_demand(customer);
% 分载条件检查
if new_load > params.vehicle_capacity
% 处理单个客户超容的情况
if isempty(segment)
extra_count = extra_count + 1;
extra_vehicles(end+1) = struct(...
'customers', customer,...
'count', 1,...
'cost', params.c0 + params.cr1);
i = i + 1; % 跳过当前客户
break;
end
% 正常分载处理
break;
end
segment = [segment, customer];
current_load = new_load;
end
if ~isempty(segment)
vehicle_routes{end+1} = segment;
i = i + length(segment);
end
% 记录额外车辆数
if extra_count > 0
extra_vehicles(end).count = extra_count;
end
end
end
%% 修改后的成本计算函数
function [node_cost, extra_info] = calculateNodeCost(route_order, depot_id, params, distance_matrix)
[vehicle_routes, extra_vehicles] = enhancedSplitRoutes(route_order, depot_id, params, distance_matrix);
transport_cost = 0;
% 常规运输成本
for v = 1:length(vehicle_routes)
segment = vehicle_routes{v};
transport_cost = transport_cost + calculateSegmentCost(segment, depot_id, params, distance_matrix);
end
% 额外车辆成本
extra_cost = sum([extra_vehicles.cost]) .* sum([extra_vehicles.count]);
% 总成本计算
node_cost = transport_cost + ...
(length(vehicle_routes) * (params.cr1 + params.c0)) + ...
extra_cost;
% 返回额外车辆信息
extra_info = extra_vehicles;
end
最新发布