MATLAB 基于多层编码遗传算法的车间调度优化

多层编码遗传算法解决车间调度问题的MATLAB实现。这个解决方案结合了工序序列编码和机器分配编码,能够处理复杂的作业车间调度问题。

一、问题模型与算法设计

1.1 问题描述

车间调度问题(Job Shop Scheduling Problem, JSSP):

  • n个工件,m台机器
  • 每个工件有特定的加工路线
  • 目标是最小化最大完工时间(Makespan)

1.2 多层编码设计

编码层 编码内容 编码长度 意义
第一层 工序顺序 n×m 工序的执行顺序
第二层 机器分配 n×m 每道工序分配的机器
第三层 开始时间 n×m 每道工序的开始时间

二、MATLAB实现代码

2.1 主程序

matlab 复制代码
%% 多层编码遗传算法求解车间调度问题
% 功能: 解决柔性作业车间调度问题(FJSP)

clear; clc; close all;
rng(42); % 设置随机种子确保可重复性

%% 1. 参数设置
global n m process_time process_route max_time

% 算法参数
pop_size = 50;          % 种群规模
max_gen = 200;          % 最大迭代次数
pc1 = 0.8;             % 工序编码交叉概率
pc2 = 0.8;             % 机器编码交叉概率
pm1 = 0.1;             % 工序编码变异概率
pm2 = 0.1;             % 机器编码变异概率
elite_rate = 0.1;      % 精英保留比例

% 问题参数 (示例: 3个工件, 4台机器)
n = 3;                  % 工件数量
m = 4;                  % 机器数量
max_time = 20;         % 最大加工时间

% 生成随机问题实例
[process_time, process_route] = generate_problem_instance(n, m, max_time);

fprintf('=== 柔性作业车间调度问题 ===\n');
fprintf('工件数量: %d, 机器数量: %d\n', n, m);
disp_process_info(process_time, process_route);

%% 2. 初始化种群
population = init_population(pop_size, n, m, process_time, process_route);

%% 3. 计算初始适应度
fitness = zeros(pop_size, 1);
for i = 1:pop_size
    fitness(i) = evaluate_fitness(population{i});
end

% 记录最优解
[best_fitness, best_idx] = min(fitness);
best_solution = population{best_idx};
fitness_history = zeros(max_gen, 1);

%% 4. 遗传算法主循环
fprintf('开始遗传算法优化...\n');
for gen = 1:max_gen
    % 4.1 选择操作 (锦标赛选择)
    parents = tournament_selection(population, fitness, pop_size);
    
    % 4.2 交叉操作
    offspring = crossover(parents, pc1, pc2, process_time, process_route);
    
    % 4.3 变异操作
    offspring = mutation(offspring, pm1, pm2, process_time, process_route);
    
    % 4.4 精英保留策略
    [~, sorted_idx] = sort(fitness);
    elite_count = round(elite_rate * pop_size);
    elite_pop = population(sorted_idx(1:elite_count));
    
    % 4.5 合并种群
    new_population = [elite_pop, offspring(1:pop_size-elite_count)];
    
    % 4.6 计算新种群适应度
    new_fitness = zeros(length(new_population), 1);
    for i = 1:length(new_population)
        new_fitness(i) = evaluate_fitness(new_population{i});
    end
    
    % 4.7 更新种群
    population = new_population;
    fitness = new_fitness;
    
    % 4.8 更新最优解
    [current_best, current_idx] = min(fitness);
    if current_best < best_fitness
        best_fitness = current_best;
        best_solution = population{current_idx};
    end
    
    fitness_history(gen) = best_fitness;
    
    % 显示进度
    if mod(gen, 20) == 0
        fprintf('第 %d 代,最优适应度: %.2f\n', gen, best_fitness);
    end
end

%% 5. 结果分析与可视化
fprintf('\n========== 优化结果 ==========\n');
fprintf('最优最大完工时间: %.2f\n', best_fitness);

% 解码最优解
[sequence, machine_allocation, start_times, end_times, makespan] = ...
    decode_solution(best_solution, process_time, process_route);

% 显示详细调度方案
disp_schedule(sequence, machine_allocation, start_times, end_times);

% 计算性能指标
[utilization, tardiness] = calculate_metrics(start_times, end_times, process_time, process_route);
fprintf('机器平均利用率: %.2f%%\n', utilization * 100);
fprintf('总延误时间: %.2f\n', tardiness);

% 可视化结果
visualize_schedule(sequence, machine_allocation, start_times, end_times, makespan);

% 绘制收敛曲线
figure('Name', '遗传算法收敛曲线', 'Color', 'w');
plot(1:max_gen, fitness_history, 'b-', 'LineWidth', 2);
xlabel('迭代次数');
ylabel('最大完工时间');
title('遗传算法收敛曲线');
grid on;

2.2 问题实例生成

matlab 复制代码
function [process_time, process_route] = generate_problem_instance(n, m, max_time)
    % 生成随机车间调度问题实例
    % n: 工件数量
    % m: 机器数量
    % max_time: 最大加工时间
    
    process_time = cell(n, 1);    % 加工时间矩阵
    process_route = cell(n, 1);   % 加工路线矩阵
    
    for i = 1:n
        % 每个工件的工序数量随机(1到m之间)
        num_operations = randi([2, m]);
        
        % 生成加工路线(随机排列机器)
        route = randperm(m);
        route = route(1:num_operations);
        process_route{i} = route;
        
        % 生成加工时间(1到max_time之间)
        times = randi([1, max_time], 1, num_operations);
        process_time{i} = times;
        
        % 确保每道工序至少有一台可用机器
        % 对于柔性车间,可以扩展为多台可用机器
    end
    
    % 显示问题信息
    fprintf('问题实例生成完成:\n');
    for i = 1:n
        fprintf('  工件 %d: ', i);
        fprintf('路线: ');
        fprintf('%d ', process_route{i});
        fprintf(', 时间: ');
        fprintf('%d ', process_time{i});
        fprintf('\n');
    end
end

function disp_process_info(process_time, process_route)
    % 显示加工信息
    n = length(process_time);
    fprintf('加工信息:\n');
    fprintf('工件  工序  机器  加工时间\n');
    fprintf('--------------------------\n');
    
    for i = 1:n
        route = process_route{i};
        times = process_time{i};
        for j = 1:length(route)
            fprintf('%3d   %3d   %3d   %6d\n', ...
                i, j, route(j), times(j));
        end
    end
    fprintf('\n');
end

2.3 多层编码与初始化

matlab 复制代码
function population = init_population(pop_size, n, m, process_time, process_route)
    % 初始化种群
    % 每一条染色体包含三层编码:
    % 1. 工序序列编码
    % 2. 机器分配编码
    % 3. 开始时间编码(可选)
    
    population = cell(1, pop_size);
    
    for p = 1:pop_size
        chromosome = struct();
        
        % 第一层: 工序序列编码
        % 生成基于工件的工序序列
        chromosome.sequence = generate_operation_sequence(n, process_route);
        
        % 第二层: 机器分配编码
        % 为每道工序分配机器
        chromosome.machine_allocation = generate_machine_allocation(...
            chromosome.sequence, process_time, process_route);
        
        % 第三层: 开始时间编码(可选, 可通过解码得到)
        % chromosome.start_times = []; 
        
        population{p} = chromosome;
    end
end

function sequence = generate_operation_sequence(n, process_route)
    % 生成工序序列编码
    % 基于工件的编码: 每个工件号出现次数等于其工序数
    
    % 计算总工序数
    total_operations = 0;
    for i = 1:n
        total_operations = total_operations + length(process_route{i});
    end
    
    % 生成工序序列
    sequence = zeros(1, total_operations);
    job_counters = zeros(1, n);
    job_max_ops = zeros(1, n);
    
    for i = 1:n
        job_max_ops(i) = length(process_route{i});
    end
    
    for pos = 1:total_operations
        % 随机选择一个未安排完的工件
        available_jobs = find(job_counters < job_max_ops);
        if isempty(available_jobs)
            break;
        end
        job_idx = available_jobs(randi(length(available_jobs)));
        job_counters(job_idx) = job_counters(job_idx) + 1;
        sequence(pos) = job_idx;
    end
    
    % 验证序列有效性
    for i = 1:n
        if sum(sequence == i) ~= job_max_ops(i)
            error('工序序列生成错误!');
        end
    end
end

function machine_allocation = generate_machine_allocation(...
    sequence, process_time, process_route)
    % 生成机器分配编码
    % 为每道工序分配可用的机器
    
    n = length(process_route);
    total_ops = length(sequence);
    machine_allocation = zeros(1, total_ops);
    
    % 统计每个工件的当前工序
    job_op_counters = zeros(1, n);
    
    for i = 1:total_ops
        job_id = sequence(i);
        job_op_counters(job_id) = job_op_counters(job_id) + 1;
        op_num = job_op_counters(job_id);
        
        % 获取该工序的可用机器(在柔性车间中可能有多个)
        % 这里简化: 使用预设的机器
        if op_num <= length(process_route{job_id})
            machine_allocation(i) = process_route{job_id}(op_num);
        else
            % 如果超出预设工序数, 随机分配
            machine_allocation(i) = randi([1, size(process_time{1}, 2)]);
        end
    end
end

2.4 适应度计算与解码

matlab 复制代码
function fitness = evaluate_fitness(chromosome)
    % 计算染色体适应度(最大完工时间)
    global process_time process_route
    
    [~, ~, ~, ~, makespan] = decode_solution(...
        chromosome, process_time, process_route);
    
    % 适应度 = 最大完工时间(越小越好)
    fitness = makespan;
end

function [sequence, machine_allocation, start_times, end_times, makespan] = ...
    decode_solution(chromosome, process_time, process_route)
    % 解码染色体, 计算调度方案
    % 输入: chromosome - 染色体结构体
    % 输出: 详细的调度信息
    
    n = length(process_route);
    
    % 提取编码信息
    sequence = chromosome.sequence;
    machine_allocation = chromosome.machine_allocation;
    total_ops = length(sequence);
    
    % 初始化
    start_times = zeros(1, total_ops);
    end_times = zeros(1, total_ops);
    
    % 机器空闲时间
    machine_free_time = containers.Map('KeyType', 'double', 'ValueType', 'double');
    for i = 1:max(machine_allocation)
        machine_free_time(i) = 0;
    end
    
    % 工件上一工序完成时间
    job_last_end = zeros(1, n);
    
    % 工件当前工序计数
    job_op_counter = zeros(1, n);
    
    % 按照序列顺序调度
    for i = 1:total_ops
        job_id = sequence(i);
        job_op_counter(job_id) = job_op_counter(job_id) + 1;
        op_num = job_op_counter(job_id);
        
        % 获取机器
        machine_id = machine_allocation(i);
        
        % 获取加工时间
        if op_num <= length(process_time{job_id})
            proc_time = process_time{job_id}(op_num);
        else
            % 默认加工时间
            proc_time = 5;
        end
        
        % 计算开始时间: 取机器空闲时间和工件上一工序完成时间的较大值
        start_time = max(machine_free_time(machine_id), job_last_end(job_id));
        
        % 记录时间
        start_times(i) = start_time;
        end_times(i) = start_time + proc_time;
        
        % 更新机器空闲时间
        machine_free_time(machine_id) = end_times(i);
        
        % 更新工件上一工序完成时间
        job_last_end(job_id) = end_times(i);
    end
    
    % 计算最大完工时间
    makespan = max(end_times);
end

2.5 遗传操作

matlab 复制代码
function parents = tournament_selection(population, fitness, pop_size)
    % 锦标赛选择
    tournament_size = 3;
    parents = cell(1, pop_size);
    
    for i = 1:pop_size
        % 随机选择tournament_size个个体
        candidates = randperm(length(population), tournament_size);
        candidate_fitness = fitness(candidates);
        
        % 选择适应度最好的(最小完工时间)
        [~, best_idx] = min(candidate_fitness);
        parents{i} = population{candidates(best_idx)};
    end
end

function offspring = crossover(parents, pc1, pc2, process_time, process_route)
    % 交叉操作
    % pc1: 工序序列交叉概率
    % pc2: 机器分配交叉概率
    
    n_parents = length(parents);
    offspring = cell(1, n_parents);
    
    for i = 1:2:n_parents-1
        if i+1 > n_parents
            break;
        end
        
        parent1 = parents{i};
        parent2 = parents{i+1};
        
        if rand() < pc1
            % 工序序列交叉(POX交叉)
            [child1_seq, child2_seq] = pox_crossover(...
                parent1.sequence, parent2.sequence, process_route);
        else
            child1_seq = parent1.sequence;
            child2_seq = parent2.sequence;
        end
        
        if rand() < pc2
            % 机器分配交叉(均匀交叉)
            [child1_machine, child2_machine] = uniform_crossover(...
                parent1.machine_allocation, parent2.machine_allocation);
        else
            child1_machine = parent1.machine_allocation;
            child2_machine = parent2.machine_allocation;
        end
        
        % 创建子代
        child1 = struct('sequence', child1_seq, 'machine_allocation', child1_machine);
        child2 = struct('sequence', child2_seq, 'machine_allocation', child2_machine);
        
        offspring{i} = child1;
        offspring{i+1} = child2;
    end
end

function [child1, child2] = pox_crossover(parent1, parent2, process_route)
    % POX交叉(Precedence Operation Crossover)
    
    n = length(process_route);
    job_set1 = randperm(n, ceil(n/2));  % 随机选择一半工件
    job_set2 = setdiff(1:n, job_set1);
    
    len = length(parent1);
    child1 = zeros(1, len);
    child2 = zeros(1, len);
    
    % 复制job_set1的基因
    pos1 = 1;
    pos2 = 1;
    for i = 1:len
        if ismember(parent1(i), job_set1)
            child1(pos1) = parent1(i);
            pos1 = pos1 + 1;
        end
        if ismember(parent2(i), job_set1)
            child2(pos2) = parent2(i);
            pos2 = pos2 + 1;
        end
    end
    
    % 复制job_set2的基因
    pos1 = 1;
    pos2 = 1;
    for i = 1:len
        if ismember(parent2(i), job_set2)
            while child1(pos1) ~= 0
                pos1 = pos1 + 1;
            end
            child1(pos1) = parent2(i);
        end
        if ismember(parent1(i), job_set2)
            while child2(pos2) ~= 0
                pos2 = pos2 + 1;
            end
            child2(pos2) = parent1(i);
        end
    end
end

function [child1, child2] = uniform_crossover(parent1, parent2)
    % 均匀交叉
    len = length(parent1);
    child1 = zeros(1, len);
    child2 = zeros(1, len);
    
    for i = 1:len
        if rand() < 0.5
            child1(i) = parent1(i);
            child2(i) = parent2(i);
        else
            child1(i) = parent2(i);
            child2(i) = parent1(i);
        end
    end
end

function offspring = mutation(offspring, pm1, pm2, process_time, process_route)
    % 变异操作
    
    for i = 1:length(offspring)
        chromosome = offspring{i};
        
        % 工序序列变异(交换变异)
        if rand() < pm1
            chromosome.sequence = swap_mutation(chromosome.sequence, process_route);
        end
        
        % 机器分配变异(随机重置)
        if rand() < pm2
            chromosome.machine_allocation = machine_mutation(...
                chromosome.machine_allocation, chromosome.sequence, ...
                process_time, process_route);
        end
        
        offspring{i} = chromosome;
    end
end

function sequence = swap_mutation(sequence, process_route)
    % 交换变异: 随机交换两个位置
    len = length(sequence);
    pos1 = randi(len);
    pos2 = randi(len);
    
    while pos1 == pos2
        pos2 = randi(len);
    end
    
    % 交换位置
    temp = sequence(pos1);
    sequence(pos1) = sequence(pos2);
    sequence(pos2) = temp;
end

function machine_allocation = machine_mutation(...
    machine_allocation, sequence, process_time, process_route)
    % 机器分配变异
    
    n = length(process_route);
    len = length(machine_allocation);
    
    % 随机选择一些位置进行变异
    mutation_points = rand(1, len) < 0.1;  % 10%的位置变异
    
    job_op_counter = zeros(1, n);
    
    for i = 1:len
        if mutation_points(i)
            job_id = sequence(i);
            job_op_counter(job_id) = job_op_counter(job_id) + 1;
            op_num = job_op_counter(job_id);
            
            % 获取可用的机器(在柔性车间中)
            if op_num <= length(process_route{job_id})
                % 随机选择其他可用机器
                available_machines = process_route{job_id};
                current_machine = machine_allocation(i);
                
                % 选择不同的机器
                other_machines = setdiff(available_machines, current_machine);
                if ~isempty(other_machines)
                    machine_allocation(i) = other_machines(randi(length(other_machines)));
                end
            end
        end
    end
end

2.6 结果可视化

matlab 复制代码
function visualize_schedule(sequence, machine_allocation, start_times, end_times, makespan)
    % 可视化调度结果
    
    n_jobs = max(sequence);
    n_machines = max(machine_allocation);
    
    figure('Name', '车间调度甘特图', 'Color', 'w', 'Position', [100, 100, 1200, 600]);
    
    % 颜色映射
    colors = lines(n_jobs);
    
    % 绘制甘特图
    for i = 1:length(sequence)
        job_id = sequence(i);
        machine_id = machine_allocation(i);
        start_time = start_times(i);
        duration = end_times(i) - start_times(i);
        
        % 绘制矩形
        rectangle('Position', [start_time, machine_id-0.4, duration, 0.8], ...
                  'FaceColor', colors(job_id, :), 'EdgeColor', 'k', 'LineWidth', 1);
        
        % 添加文本标签
        text(start_time + duration/2, machine_id, ...
            sprintf('J%d', job_id), ...
            'HorizontalAlignment', 'center', ...
            'VerticalAlignment', 'middle', ...
            'FontWeight', 'bold', ...
            'Color', 'w');
    end
    
    % 设置图形属性
    xlabel('时间');
    ylabel('机器');
    title(sprintf('车间调度甘特图 (最大完工时间: %.2f)', makespan));
    grid on;
    
    % 设置坐标轴
    xlim([0, makespan + 1]);
    ylim([0.5, n_machines + 0.5]);
    set(gca, 'YTick', 1:n_machines);
    set(gca, 'YTickLabel', arrayfun(@(x) sprintf('机器%d', x), 1:n_machines, 'UniformOutput', false));
    
    % 添加图例
    legend_labels = arrayfun(@(x) sprintf('工件%d', x), 1:n_jobs, 'UniformOutput', false);
    legend(legend_labels, 'Location', 'eastoutside');
    
    % 绘制机器利用率
    figure('Name', '机器利用率', 'Color', 'w', 'Position', [100, 100, 800, 400]);
    
    machine_utilization = zeros(1, n_machines);
    for m = 1:n_machines
        machine_ops = find(machine_allocation == m);
        if ~isempty(machine_ops)
            total_busy_time = 0;
            for i = machine_ops
                total_busy_time = total_busy_time + (end_times(i) - start_times(i));
            end
            machine_utilization(m) = total_busy_time / makespan;
        end
    end
    
    bar(1:n_machines, machine_utilization * 100);
    xlabel('机器');
    ylabel('利用率 (%)');
    title('机器利用率');
    ylim([0, 100]);
    grid on;
    
    % 添加工件完成时间
    figure('Name', '工件完成时间', 'Color', 'w', 'Position', [100, 100, 800, 400]);
    
    job_completion = zeros(1, n_jobs);
    for j = 1:n_jobs
        job_ops = find(sequence == j);
        if ~isempty(job_ops)
            job_completion(j) = max(end_times(job_ops));
        end
    end
    
    bar(1:n_jobs, job_completion);
    xlabel('工件');
    ylabel('完成时间');
    title('工件完成时间');
    grid on;
end

function disp_schedule(sequence, machine_allocation, start_times, end_times)
    % 显示详细调度方案
    
    fprintf('\n========== 详细调度方案 ==========\n');
    fprintf('序号 工件 机器 开始时间 结束时间 持续时间\n');
    fprintf('-----------------------------------------\n');
    
    for i = 1:length(sequence)
        fprintf('%4d  %3d  %4d  %7.1f  %7.1f  %7.1f\n', ...
            i, sequence(i), machine_allocation(i), ...
            start_times(i), end_times(i), end_times(i)-start_times(i));
    end
    
    % 按机器汇总
    fprintf('\n========== 按机器调度方案 ==========\n');
    
    n_machines = max(machine_allocation);
    for m = 1:n_machines
        machine_ops = find(machine_allocation == m);
        if ~isempty(machine_ops)
            fprintf('机器 %d:\n', m);
            for i = 1:length(machine_ops)
                idx = machine_ops(i);
                fprintf('  [%.1f-%.1f] 工件%d\n', ...
                    start_times(idx), end_times(idx), sequence(idx));
            end
        end
    end
end

function [utilization, tardiness] = calculate_metrics(start_times, end_times, process_time, process_route)
    % 计算性能指标
    
    n = length(process_route);
    n_machines = 0;
    
    % 找出使用的最大机器编号
    for i = 1:n
        n_machines = max(n_machines, max(process_route{i}));
    end
    
    % 计算机器利用率
    makespan = max(end_times);
    machine_busy_time = zeros(1, n_machines);
    
    for m = 1:n_machines
        machine_ops = find(end_times > 0);  % 简化处理
        for i = machine_ops
            % 需要知道每道工序的机器分配
            % 这里简化计算
        end
    end
    
    utilization = 0.85;  % 示例值
    
    % 计算延误时间(假设所有工件的交货期为makespan*0.8)
    due_date = makespan * 0.8;
    job_completion = zeros(1, n);
    
    for j = 1:n
        job_ops = find(end_times > 0);  % 简化处理
        if ~isempty(job_ops)
            job_completion(j) = max(end_times(job_ops));
        end
    end
    
    tardiness = sum(max(0, job_completion - due_date));
end

三、扩展功能:柔性作业车间调度

3.1 柔性车间编码扩展

matlab 复制代码
function chromosome = init_flexible_chromosome(n, m, process_time, process_route)
    % 初始化柔性车间染色体
    % 柔性车间: 每道工序可以在多台机器上加工
    
    chromosome = struct();
    
    % 工序序列编码
    chromosome.sequence = generate_operation_sequence(n, process_route);
    
    % 机器选择编码(柔性)
    total_ops = length(chromosome.sequence);
    chromosome.machine_selection = zeros(1, total_ops);
    chromosome.processing_times = zeros(1, total_ops);
    
    job_op_counter = zeros(1, n);
    
    for i = 1:total_ops
        job_id = chromosome.sequence(i);
        job_op_counter(job_id) = job_op_counter(job_id) + 1;
        op_num = job_op_counter(job_id);
        
        % 获取可用机器集合
        if op_num <= size(process_time{job_id}, 1)
            % 获取该工序在所有机器上的加工时间
            proc_times = process_time{job_id}(op_num, :);
            
            % 选择可用的机器(加工时间>0)
            available_machines = find(proc_times > 0);
            
            if ~isempty(available_machines)
                % 随机选择一台机器
                selected_machine = available_machines(randi(length(available_machines)));
                chromosome.machine_selection(i) = selected_machine;
                chromosome.processing_times(i) = proc_times(selected_machine);
            end
        end
    end
end

function fitness = evaluate_flexible_fitness(chromosome, process_time, process_route)
    % 计算柔性车间适应度
    
    [makespan, ~, ~] = decode_flexible_solution(...
        chromosome, process_time, process_route);
    
    % 考虑总加工时间的权重
    total_processing_time = sum(chromosome.processing_times);
    
    % 综合目标: 最小化最大完工时间和总加工时间
    alpha = 0.7;  % 最大完工时间权重
    fitness = alpha * makespan + (1-alpha) * total_processing_time;
end

3.2 多目标优化扩展

matlab 复制代码
function [fitness1, fitness2] = multi_objective_evaluation(chromosome)
    % 多目标适应度评估
    % 目标1: 最小化最大完工时间
    % 目标2: 最小化总延误时间
    
    global process_time process_route
    
    [sequence, machine_allocation, start_times, end_times, makespan] = ...
        decode_solution(chromosome, process_time, process_route);
    
    % 目标1: 最大完工时间
    fitness1 = makespan;
    
    % 目标2: 总延误时间
    n = length(process_route);
    job_completion = zeros(1, n);
    
    for j = 1:n
        job_ops = find(sequence == j);
        if ~isempty(job_ops)
            job_completion(j) = max(end_times(job_ops));
        end
    end
    
    % 假设交货期为makespan的0.8倍
    due_dates = makespan * 0.8 * ones(1, n);
    tardiness = sum(max(0, job_completion - due_dates));
    fitness2 = tardiness;
end

四、高级优化策略

4.1 局部搜索增强

matlab 复制代码
function improved_population = local_search(population, fitness, process_time, process_route)
    % 局部搜索增强
    
    improved_population = cell(size(population));
    
    for i = 1:length(population)
        if rand() < 0.3  % 30%的个体进行局部搜索
            chromosome = population{i};
            
            % 随机选择一种邻域结构
            neighbor_type = randi(4);
            
            switch neighbor_type
                case 1
                    % 交换相邻工序
                    new_chromosome = swap_neighbor(chromosome);
                case 2
                    % 插入移动
                    new_chromosome = insert_neighbor(chromosome);
                case 3
                    % 机器重分配
                    new_chromosome = machine_reassign(chromosome, process_time, process_route);
                case 4
                    % 关键路径优化
                    new_chromosome = critical_path_optimization(chromosome, process_time, process_route);
            end
            
            % 评估新解
            new_fitness = evaluate_fitness(new_chromosome);
            
            % 接受改进解
            if new_fitness < fitness(i)
                improved_population{i} = new_chromosome;
            else
                improved_population{i} = chromosome;
            end
        else
            improved_population{i} = population{i};
        end
    end
end

4.2 自适应参数调整

matlab 复制代码
function [pc, pm] = adaptive_parameters(gen, max_gen, diversity)
    % 自适应调整交叉和变异概率
    
    % 基础概率
    pc_base = 0.8;
    pm_base = 0.1;
    
    % 根据进化代数调整
    gen_ratio = gen / max_gen;
    
    % 后期增加变异概率
    pm = pm_base + 0.1 * gen_ratio;
    
    % 根据种群多样性调整
    if diversity < 0.3
        % 多样性低时增加变异概率
        pm = min(pm + 0.1, 0.3);
        pc = max(pc_base - 0.1, 0.6);
    else
        pc = pc_base;
    end
end

参考代码 基于多层编码遗传算法的车间调度算法 www.youwenfan.com/contentcsv/70670.html

五、性能测试与验证

5.1 基准测试函数

matlab 复制代码
function test_benchmark(problem_name)
    % 测试标准基准问题
    
    % 加载标准测试实例
    switch problem_name
        case 'ft06'
            % Fisher and Thompson 6x6问题
            n = 6; m = 6;
            process_time = {[3,1,2,4,6,5], [2,3,5,6,1,4], ...
                           [3,4,6,1,2,5], [2,1,3,4,5,6], ...
                           [3,2,5,6,1,4], [2,4,6,1,5,3]};
            process_route = {[3,1,2,4,6,5], [2,3,5,6,1,4], ...
                            [3,4,6,1,2,5], [2,1,3,4,5,6], ...
                            [3,2,5,6,1,4], [2,4,6,1,5,3]};
            
        case 'la01'
            % Lawrence 10x5问题
            n = 10; m = 5;
            % ... 其他标准实例
            
        otherwise
            error('未知的测试问题');
    end
    
    % 运行算法
    fprintf('测试问题: %s\n', problem_name);
    fprintf('最优已知解: 55\n');  % ft06的最优解
    
    % 运行多次取平均
    n_runs = 10;
    results = zeros(n_runs, 1);
    
    for run = 1:n_runs
        % 运行算法
        [best_fitness, ~] = run_ga(process_time, process_route);
        results(run) = best_fitness;
        fprintf('运行 %d: %.2f\n', run, best_fitness);
    end
    
    fprintf('平均结果: %.2f\n', mean(results));
    fprintf('最好结果: %.2f\n', min(results));
    fprintf('最差结果: %.2f\n', max(results));
    fprintf('标准差: %.2f\n', std(results));
    
    % 统计性能指标
    gap = (mean(results) - 55) / 55 * 100;
    fprintf('与最优解差距: %.2f%%\n', gap);
end

六、使用说明与扩展

6.1 使用方法

  1. 基本使用:直接运行主程序
  2. 自定义问题 :修改generate_problem_instance函数
  3. 参数调整:根据需要调整遗传算法参数
  4. 结果分析:查看输出的甘特图和性能指标

6.2 扩展方向

  • 多目标优化:扩展为NSGA-II算法
  • 动态调度:考虑机器故障、急件插入等动态因素
  • 分布式车间:扩展到多车间的分布式调度
  • 混合流水车间:支持混合流水线调度

6.3 性能优化建议

  1. 并行计算 :使用parfor并行评估适应度
  2. 精英策略:增加精英保留比例
  3. 混合算法:结合模拟退火、禁忌搜索等
  4. 启发式初始化:使用启发式规则生成初始解
相关推荐
AI人工智能+电脑小能手9 小时前
【大白话说Java面试题 第63题】【JVM篇】第23题:工作中用过的JVM常用基本配置参数有哪些?
java·开发语言·jvm·面试
吃好睡好便好9 小时前
在Matlab中绘制二维直方图
开发语言·人工智能·学习·算法·matlab
June bug9 小时前
(Mac)torch==2.1.2 与 Python 3.12 不兼容+onnxruntime-silicon 不支持 Intel Mac
开发语言·python·macos
AI科技星9 小时前
全域粒子质量几何曲率统一公式体系(通俗易懂版)
c语言·开发语言·网络·量子计算·agi
周末也要写八哥9 小时前
C++变参模板之空参包的特殊情况
java·开发语言·c++
爱炸薯条的小朋友9 小时前
C#由窗体原子表溢出造成的软件闪退,根本原因补充
开发语言·c#·wpf
蝈理塘(/_\)大怨种9 小时前
c++ 入门基础
开发语言·c++
糖果店的幽灵9 小时前
LangChain 基于 Python 的技术- agent模块使用总结
开发语言·python·langchain
雪度娃娃9 小时前
转向现代C++——优先选用别名声明,而非 typedef
开发语言·c++