%% 完整物流路径优化方案(修正版)
% 包含以下改进:
% 1. 参数集中管理
% 2. 输入验证机制
% 3. 性能优化
% 4. 可视化增强
%% 主程序框架
function main_logistics_optimization()
% 初始化环境
clear; clc; close all;
%% 数据加载模块
try
[node_coords, customer_data] = load_input_data();
catch ME
error('数据加载失败: %s', ME.message);
end
%% 参数配置
params = initialize_parameters(node_coords, customer_data);
%% 距离矩阵生成(带缓存)
if exist('distance_matrix.mat', 'file')
load('distance_matrix.mat', 'distance_matrix');
else
distance_matrix = create_distance_matrix(...
[params.node_coords; params.customer_coords],...
params.distance_method);
save('distance_matrix.mat', 'distance_matrix');
end
%% 遗传算法优化
[best_solution, best_cost] = genetic_algorithm_optimizer(params, distance_matrix);
%% 结果展示
visualize_results(best_solution, params, distance_matrix);
end
%% 数据加载函数(带验证)
function [node_coords, customer_data] = load_input_data()
% 修正后的坐标定义与验证
try
% 正确声明原始坐标变量
raw_node_coords = [ % 变量名修正为raw_node_coords
108.2159 33.1062
108.2766 33.1397
108.3082 33.0527
108.2666 33.0092
108.2160 33.0834];
% 使用正确的变量名进行验证
node_coords = validate_node_coordinates(raw_node_coords);
validateattributes(node_coords, {'numeric'},...
{'ncols',2, '>=', 100, '<=', 150}, 'load_input_data', '节点坐标');
% 增强型客户数据加载
try
[~, ~, raw] = xlsread('工作簿2.xlsx', 'Sheet1');
% 数据清洗
raw(cellfun(@(x) any(ismissing(x)), raw)) = {0}; % 处理缺失值
customer_data = cell2mat(raw);
% 列数验证
if size(customer_data,2) < 4
error('客户数据需要至少4列(坐标X,Y + 配送需求 + 回收需求)');
end
% 截断多余列
customer_data = customer_data(:,1:4);
catch ME
% 详细错误报告
fprintf('数据加载错误详情:\n');
fprintf('错误类型:%s\n', ME.identifier);
fprintf('错误信息:%s\n', ME.message);
% 安全示例数据生成
warning('生成安全示例数据...');
num_samples = 20;
customer_data = [...
rand(num_samples,2).*[0.1 0.1] + [108.2 33.0],... % 坐标
randi([3,8], num_samples,1),... % 配送需求
randi([1,5], num_samples,1)]; % 回收需求
end
% 增强验证
validateattributes(customer_data, {'numeric'},...
{'ncols',4, 'nonempty', 'nonnan'},...
'load_input_data', '客户数据');
% 范围验证
assert(all(customer_data(:,1) >= 108.0 & customer_data(:,1) <= 108.5),...
'X坐标超出合理范围');
assert(all(customer_data(:,2) >= 33.0 & customer_data(:,2) <= 33.2),...
'Y坐标超出合理范围');
assert(all(customer_data(:,3) >= 0), '配送需求不能为负');
assert(all(customer_data(:,4) >= 0), '回收需求不能为负');
end
end
%% 参数初始化函数
function params = initialize_parameters(node_coords, customer_data)
params = struct();
% 基础参数
params.node_coords = node_coords;
params.customer_coords = customer_data(:,1:2);
params.delivery_demand = customer_data(:,3);
params.recycle_demand = customer_data(:,4);
% 物流参数
params.vehicle_capacity = 10; % 单车运载量
params.depot_capacity = 10000; % 节点服务能力
params.operating_cost = 160000; % 节点运营成本
params.distance_cost = 1.5; % 单位距离成本
params.max_distance = 400; % 单程最大距离(km)
% 遗传算法参数
params.pop_size = 100; % 种群数量
params.max_gen = 200; % 最大迭代次数
params.cross_rate = 0.85; % 交叉概率
params.mutate_rate = 0.1; % 变异概率
params.distance_method = 'euclidean'; % 距离计算方法
end
%% 优化器核心
function [best_solution, best_cost] = genetic_algorithm_optimizer(params, distance_matrix)
% 种群初始化
population = initialize_population(params);
% 进化循环
best_cost = Inf;
cost_history = zeros(params.max_gen, 1);
for gen = 1:params.max_gen
% 计算适应度
costs = evaluate_population(population, params, distance_matrix);
% 记录最佳解
[min_cost, idx] = min(costs);
cost_history(gen) = min_cost;
if min_cost < best_cost
best_solution = population{idx};
best_cost = min_cost;
fprintf('Generation %d: 新最优成本 %.2f\n', gen, best_cost);
end
% 进化操作
population = evolve_population(population, costs, params);
end
% 收敛曲线可视化
figure;
plot(cost_history, 'LineWidth',2);
title('收敛曲线');
xlabel('迭代次数');
ylabel('最低成本');
grid on;
end
%% 种群初始化(带有效性验证)
function population = initialize_population(params)
population = cell(params.pop_size, 1);
num_cust = size(params.customer_coords, 1);
num_nodes = size(params.node_coords, 1);
for i = 1:params.pop_size
while true
chrom = create_chromosome(num_nodes, num_cust);
if validate_chromosome(chrom, params)
population{i} = chrom;
break;
end
end
end
end
%% 染色体生成函数
function chrom = create_chromosome(num_nodes, num_cust)
allocation = randi(num_nodes, 1, num_cust);
sequence = randperm(num_cust);
chrom = [allocation, sequence];
end
%% 染色体有效性验证
function valid = validate_chromosome(chrom, params)
num_cust = length(params.delivery_demand);
% 基本结构验证
if length(chrom) ~= 2*num_cust
valid = false;
return;
end
% 分配有效性验证
allocation = chrom(1:num_cust);
if any(allocation < 1 | allocation > size(params.node_coords,1))
valid = false;
return;
end
% 路径序列验证
sequence = chrom(num_cust+1:end);
if length(unique(sequence)) ~= num_cust || any(sequence < 1 | sequence > num_cust)
valid = false;
return;
end
valid = true;
end
%% 适应度计算(优化版)
function costs = evaluate_population(population, params, distance_matrix)
costs = zeros(size(population));
parfor i = 1:numel(population) % 启用并行计算
costs(i) = calculate_fitness(population{i}, params, distance_matrix);
end
end
%% 改进的适应度计算函数
function total_cost = calculate_fitness(chrom, params, distance_matrix)
% 参数解包
num_nodes = size(params.node_coords, 1);
num_cust = size(params.customer_coords, 1);
% 解析染色体
allocation = chrom(1:num_cust);
sequence = chrom(num_cust+1:end);
% 初始化成本
total_cost = 0;
% 节点循环
for n = 1:num_nodes
% 当前节点的客户索引
node_customers = find(allocation == n);
% 计算节点总需求
total_demand = sum(params.delivery_demand(node_customers));
% 能力约束检查
if total_demand > params.depot_capacity
total_cost = total_cost + 1e6; % 大惩罚项
continue;
end
% 路径规划
if ~isempty(node_customers)
% 获取排序后的路径
[~, order] = ismember(node_customers, sequence);
[~, sorted_idx] = sort(order);
route_order = node_customers(sorted_idx);
% 车辆调度计算
[route_cost, vehicle_count] = vehicle_dispatch(...
route_order, n, params, distance_matrix);
% 累加成本
total_cost = total_cost + route_cost + ...
params.operating_cost + ...
vehicle_count * 8000; % 车辆固定成本
end
end
end
%% 车辆调度核心算法
function [route_cost, vehicle_count] = vehicle_dispatch(route_order, node_id, params, distance_matrix)
route_cost = 0;
vehicle_count = 0;
current_load = 0;
current_distance = 0;
last_point = node_id;
for i = 1:length(route_order)
customer_idx = route_order(i) + size(params.node_coords,1);
seg_distance = distance_matrix(last_point, customer_idx);
% 约束检查
if (current_load + params.delivery_demand(route_order(i)) > params.vehicle_capacity) || ...
(current_distance + seg_distance > params.max_distance)
% 返回节点
return_distance = distance_matrix(last_point, node_id);
route_cost = route_cost + (current_distance + return_distance) * params.distance_cost;
% 新车辆
vehicle_count = vehicle_count + 1;
current_load = 0;
current_distance = 0;
last_point = node_id;
end
% 更新状态
current_load = current_load + params.delivery_demand(route_order(i));
current_distance = current_distance + seg_distance;
last_point = customer_idx;
end
% 处理最后未完成的路线
if current_distance > 0
return_distance = distance_matrix(last_point, node_id);
route_cost = route_cost + (current_distance + return_distance) * params.distance_cost;
vehicle_count = vehicle_count + 1;
end
end
%% 进化操作
function new_population = evolve_population(population, costs, params)
% 选择操作
selected = tournament_selection(population, costs, params.pop_size);
% 交叉操作
new_population = crossover_operation(selected, params);
% 变异操作
new_population = mutation_operation(new_population, params);
end
%% 锦标赛选择
function selected = tournament_selection(population, costs, pop_size)
selected = cell(pop_size, 1);
tournament_size = 3;
for i = 1:pop_size
candidates = randperm(length(population), tournament_size);
[~, idx] = min(costs(candidates));
selected{i} = population{candidates(idx)};
end
end
%% 增强型交叉操作
function new_population = crossover_operation(population, params)
new_population = cell(size(population));
num_parents = length(population);
num_cust = floor(length(population{1}) / 2);
for i = 1:2:num_parents
if rand() < params.cross_rate
parent1 = population{i};
parent2 = population{i+1};
% 改进的交叉策略
[child1, child2] = enhanced_crossover(parent1, parent2, num_cust);
new_population{i} = child1;
new_population{i+1} = child2;
else
new_population{i} = population{i};
new_population{i+1} = population{i+1};
end
end
end
%% 增强型交叉函数
function [child1, child2] = enhanced_crossover(parent1, parent2, num_cust)
% 分配部分交叉
mask = rand(1, num_cust) > 0.5;
child1_alloc = parent1(1:num_cust).*mask + parent2(1:num_cust).*(~mask);
child2_alloc = parent1(1:num_cust).*(~mask) + parent2(1:num_cust).*mask;
% 路径顺序交叉
[child1_seq, child2_seq] = ox_crossover(...
parent1(num_cust+1:end),...
parent2(num_cust+1:end));
child1 = [child1_alloc, child1_seq];
child2 = [child2_alloc, child2_seq];
end
%% 变异操作
function population = mutation_operation(population, params)
num_cust = floor(length(population{1}) / 2);
num_nodes = size(params.node_coords,1);
for i = 1:numel(population)
if rand() < params.mutate_rate
population{i} = guided_mutation(population{i}, num_nodes, num_cust);
end
end
end
%% 指导式变异
function mutated = guided_mutation(chrom, num_nodes, num_cust)
if rand() < 0.7
% 分配变异
pos = randi(num_cust);
mutated = chrom;
mutated(pos) = randi(num_nodes);
else
% 路径变异
seq = chrom(num_cust+1:end);
swap_pos = randperm(num_cust, 2);
seq(swap_pos) = seq(fliplr(swap_pos));
mutated = [chrom(1:num_cust), seq];
end
end
%% 可视化模块增强
function visualize_results(solution, params, distance_matrix)
figure('Position', [100, 100, 1200, 800]);
% 基础可视化
subplot(2,2,[1,3]);
visualize_routes(solution, params);
% 距离矩阵可视化
subplot(2,2,2);
imagesc(distance_matrix);
colorbar;
title('距离矩阵');
% 需求分布可视化
subplot(2,2,4);
bar([params.delivery_demand, params.recycle_demand]);
title('客户需求分布');
xlabel('客户编号');
ylabel('需求量');
legend('配送需求', '回收需求');
end
%% 增强版路径可视化
function visualize_routes(chrom, params)
hold on;
% 绘制节点
scatter(params.node_coords(:,1), params.node_coords(:,2),...
150, 'k^', 'filled', 'DisplayName', '配送中心');
% 绘制客户
scatter(params.customer_coords(:,1), params.customer_coords(:,2),...
80, 'bo', 'filled', 'DisplayName', '客户点');
% 解析路径
num_cust = size(params.customer_coords,1);
allocation = chrom(1:num_cust);
sequence = chrom(num_cust+1:end);
colors = lines(size(params.node_coords,1));
for n = 1:size(params.node_coords,1)
node_customers = find(allocation == n);
if ~isempty(node_customers)
% 获取排序路径
[~, order] = ismember(node_customers, sequence);
[~, sorted_idx] = sort(order);
sorted_customers = node_customers(sorted_idx);
% 构建完整路径
route = [params.node_coords(n,:);
params.customer_coords(sorted_customers,:);
params.node_coords(n,:)];
% 绘制路径
plot(route(:,1), route(:,2), 'Color', colors(n,:),...
'LineWidth', 1.5, 'DisplayName', sprintf('路径%d',n));
end
end
hold off;
title('最优配送路径');
xlabel('经度');
ylabel('纬度');
legend('Location','bestoutside');
grid on;
end
function node_coords = validate_node_coordinates(input_coords)
% 参数验证增强版(分经度/纬度验证)
try
% 基础结构验证
validateattributes(input_coords, {'numeric'},...
{'2d', 'ncols',2, 'real', 'finite'},...
'validate_node_coordinates', '节点坐标');
% 分列范围验证
valid_lon_range = [100 120]; % 合理经度范围(中国地区)
valid_lat_range = [20 40]; % 合理纬度范围(中国地区)
% 经度验证(第一列)
validateattributes(input_coords(:,1), {'numeric'},...
{'>=', valid_lon_range(1), '<=', valid_lon_range(2)},...
'validate_node_coordinates', '经度值');
% 纬度验证(第二列)
validateattributes(input_coords(:,2), {'numeric'},...
{'>=', valid_lat_range(1), '<=', valid_lat_range(2)},...
'validate_node_coordinates', '纬度值');
node_coords = input_coords;
catch ME
% 智能修正机制
fprintf('坐标验证错误:%s\n', ME.message);
fprintf('启动自动地理修正...\n');
% 保留原始数据结构
node_coords = input_coords;
% 经度修正(第一列)
node_coords(:,1) = max(node_coords(:,1), valid_lon_range(1));
node_coords(:,1) = min(node_coords(:,1), valid_lon_range(2));
% 纬度修正(第二列)
node_coords(:,2) = max(node_coords(:,2), valid_lat_range(1));
node_coords(:,2) = min(node_coords(:,2), valid_lat_range(2));
% 修正后验证
validateattributes(node_coords, {'numeric'},...
{'2d', 'ncols',2}, 'validate_node_coordinates', '修正后坐标');
warning('已自动修正坐标至有效范围:\n%s', mat2str(node_coords));
end
end