基于基因演算法(GA)的柔性作业车间调度问题(FJSP)求解

基于基因演算法(GA)的柔性作业车间调度问题(FJSP)求解

一、问题定义与数学模型

1.1 柔性作业车间调度问题(FJSP)

FJSP是经典作业车间调度问题(JSP)的扩展,每个工序可在多台机器上加工,且加工时间不同。

问题描述

目标:最小化最大完工时间(Makespan)

约束

  1. 工序先后约束:
  2. 机器容量约束:一台机器同一时间只能加工一个工序
  3. 工序不能中断

1.2 问题复杂度

问题规模 决策变量数 搜索空间大小
3工件×3工序×3机器 18
5工件×5工序×5机器 125
10工件×10工序×10机器 1000

二、完整MATLAB实现代码

2.1 主程序:ga_fjsp_solver.m

%% 基于基因演算法的柔性作业车间调度问题求解
% 功能:使用遗传算法求解FJSP,最小化最大完工时间

clear; clc; close all;

%% 1. 问题实例定义
fprintf('=== 柔性作业车间调度问题(FJSP)求解 ===\n');
problem = define_fjsp_instance();

fprintf('问题实例:\n');
fprintf('  工件数量: %d\n', problem.n_jobs);
fprintf('  机器数量: %d\n', problem.n_machines);
fprintf('  总工序数: %d\n', problem.total_ops);
fprintf('  搜索空间大小: %.2e\n\n', problem.search_space);

%% 2. 基因演算法参数设置
params = configure_ga_parameters(problem);

fprintf('基因演算法参数:\n');
fprintf('  种群大小: %d\n', params.pop_size);
fprintf('  最大代数: %d\n', params.max_gen);
fprintf('  交叉概率: %.2f\n', params.pc);
fprintf('  变异概率: %.2f\n', params.pm);
fprintf('  精英保留比例: %.2f\n\n', params.elite_ratio);

%% 3. 初始化种群
fprintf('初始化种群...\n');
tic;
population = initialize_population(problem, params);
init_time = toc;
fprintf('  种群初始化完成!耗时: %.3f秒\n', init_time);

%% 4. 基因演算法主循环
fprintf('开始基因演算法进化...\n');
tic;
[best_solution, best_fitness_history, avg_fitness_history] = genetic_algorithm(population, problem, params);
ga_time = toc;
fprintf('  基因演算法完成!耗时: %.3f秒\n', ga_time);

%% 5. 解码最优解并生成调度方案
fprintf('解码最优解...\n');
[schedule, makespan] = decode_solution(best_solution, problem);

fprintf('\n=== 求解结果 ===\n');
fprintf('最优最大完工时间 (Makespan): %.2f\n', makespan);
fprintf('总进化代数: %d\n', length(best_fitness_history));
fprintf('最终种群平均适应度: %.2f\n', avg_fitness_history(end));
fprintf('收敛代数: %d\n', find(best_fitness_history == min(best_fitness_history), 1, 'last'));

%% 6. 可视化结果
visualize_results(schedule, makespan, best_fitness_history, avg_fitness_history, problem);

2.2 问题实例定义:define_fjsp_instance.m

function problem = define_fjsp_instance()
    % 定义FJSP问题实例(示例:3工件×3工序×3机器)
    
    % === 基本参数 ===
    problem.n_jobs = 3;          % 工件数量
    problem.n_machines = 3;      % 机器数量
    
    % 每个工件的工序数
    problem.ops_per_job = [3, 3, 3];  % 工件1、2、3各有3个工序
    problem.total_ops = sum(problem.ops_per_job);  % 总工序数
    
    % === 可选机器矩阵 ===
    % ops_machine{i}{j}: 工件i的第j个工序可选机器集合
    % 格式: [机器索引, 加工时间]
    problem.ops_machine = cell(problem.n_jobs, max(problem.ops_per_job));
    
    % 工件1
    problem.ops_machine{1,1} = [1, 2; 2, 3];      % 工序1可选机器1(2h)或机器2(3h)
    problem.ops_machine{1,2} = [2, 2; 3, 4];      % 工序2可选机器2(2h)或机器3(4h)
    problem.ops_machine{1,3} = [1, 3; 3, 5];      % 工序3可选机器1(3h)或机器3(5h)
    
    % 工件2
    problem.ops_machine{2,1} = [1, 3; 2, 4];      % 工序1可选机器1(3h)或机器2(4h)
    problem.ops_machine{2,2} = [2, 3; 3, 5];      % 工序2可选机器2(3h)或机器3(5h)
    problem.ops_machine{2,3} = [1, 4; 3, 6];      % 工序3可选机器1(4h)或机器3(6h)
    
    % 工件3
    problem.ops_machine{3,1} = [1, 4; 2, 5];      % 工序1可选机器1(4h)或机器2(5h)
    problem.ops_machine{3,2} = [2, 4; 3, 6];      % 工序2可选机器2(4h)或机器3(6h)
    problem.ops_machine{3,3} = [1, 5; 3, 7];      % 工序3可选机器1(5h)或机器3(7h)
    
    % === 计算搜索空间 ===
    search_space = 1;
    for job = 1:problem.n_jobs
        for op = 1:problem.ops_per_job(job)
            n_options = size(problem.ops_machine{job, op}, 1);
            search_space = search_space * n_options;
        end
    end
    problem.search_space = search_space;
    
    % === 工序索引映射 ===
    % 将工序索引转换为全局索引
    problem.op_global_idx = zeros(problem.n_jobs, max(problem.ops_per_job));
    global_idx = 1;
    for job = 1:problem.n_jobs
        for op = 1:problem.ops_per_job(job)
            problem.op_global_idx(job, op) = global_idx;
            global_idx = global_idx + 1;
        end
    end
    
    fprintf('FJSP实例定义完成!\n');
end

2.3 GA参数配置:configure_ga_parameters.m

function params = configure_ga_parameters(problem)
    % 配置基因演算法参数
    
    % === 种群参数 ===
    params.pop_size = 100;           % 种群大小
    params.max_gen = 200;           % 最大进化代数
    params.elite_ratio = 0.1;       % 精英保留比例
    params.elite_count = round(params.pop_size * params.elite_ratio);
    
    % === 遗传算子参数 ===
    params.pc = 0.8;                % 交叉概率
    params.pm = 0.1;                % 变异概率
    
    % === 编码参数 ===
    params.chromosome_length = problem.total_ops * 2;  % 染色体长度:工序顺序+机器分配
    
    % === 选择参数 ===
    params.tournament_size = 3;     % 锦标赛选择大小
    
    % === 终止条件 ===
    params.stagnation_limit = 50;   % 停滞代数限制
    params.target_fitness = 1e-6;   % 目标适应度
    
    fprintf('GA参数配置完成!\n');
end

2.4 种群初始化:initialize_population.m

function population = initialize_population(problem, params)
    % 初始化种群
    
    population = cell(params.pop_size, 1);
    
    for i = 1:params.pop_size
        % 生成随机工序顺序(基于工件优先)
        op_sequence = generate_random_operation_sequence(problem);
        
        % 生成随机机器分配
        machine_assignment = generate_random_machine_assignment(op_sequence, problem);
        
        % 组合成染色体
        chromosome.op_sequence = op_sequence;
        chromosome.machine_assignment = machine_assignment;
        chromosome.fitness = inf;  % 初始适应度为无穷大
        
        population{i} = chromosome;
    end
    
    fprintf('  生成 %d 个随机个体\n', params.pop_size);
end

function op_sequence = generate_random_operation_sequence(problem)
    % 生成随机工序顺序
    % 使用优先约束:同一工件的工序必须按顺序
    
    op_sequence = zeros(1, problem.total_ops);
    op_counter = zeros(1, problem.n_jobs);
    available_jobs = 1:problem.n_jobs;
    
    for pos = 1:problem.total_ops
        % 随机选择可用的工件
        valid_jobs = [];
        for job = available_jobs
            if op_counter(job) < problem.ops_per_job(job)
                valid_jobs = [valid_jobs, job];
            end
        end
        
        % 随机选择一个工件
        selected_job = valid_jobs(randi(length(valid_jobs)));
        op_counter(selected_job) = op_counter(selected_job) + 1;
        
        % 记录工序
        op_sequence(pos) = selected_job * 100 + op_counter(selected_job);  % 编码:工件号*100+工序号
    end
end

function machine_assignment = generate_random_machine_assignment(op_sequence, problem)
    % 生成随机机器分配
    machine_assignment = zeros(1, length(op_sequence));
    
    for pos = 1:length(op_sequence)
        % 解码工序编码
        op_code = op_sequence(pos);
        job_id = floor(op_code / 100);
        op_id = mod(op_code, 100);
        
        % 获取可选机器
        machine_options = problem.ops_machine{job_id, op_id};
        n_options = size(machine_options, 1);
        
        % 随机选择一台机器
        selected_option = randi(n_options);
        machine_assignment(pos) = machine_options(selected_option, 1);  % 机器编号
    end
end

2.5 基因演算法主循环:genetic_algorithm.m

function [best_solution, best_fitness_history, avg_fitness_history] = genetic_algorithm(population, problem, params)
    % 基因演算法主循环
    
    best_fitness_history = zeros(params.max_gen, 1);
    avg_fitness_history = zeros(params.max_gen, 1);
    best_solution = population{1};
    stagnation_counter = 0;
    
    for gen = 1:params.max_gen
        % 1. 评估种群适应度
        population = evaluate_population(population, problem);
        
        % 2. 记录统计信息
        fitness_values = zeros(params.pop_size, 1);
        for i = 1:params.pop_size
            fitness_values(i) = population{i}.fitness;
        end
        
        best_fitness_history(gen) = min(fitness_values);
        avg_fitness_history(gen) = mean(fitness_values);
        
        % 3. 更新最优解
        [current_best_fitness, best_idx] = min(fitness_values);
        if current_best_fitness < best_solution.fitness
            best_solution = population{best_idx};
            stagnation_counter = 0;
        else
            stagnation_counter = stagnation_counter + 1;
        end
        
        % 4. 显示进化信息
        if mod(gen, 10) == 0 || gen == 1
            fprintf('  第 %d 代: 最佳适应度 = %.2f, 平均适应度 = %.2f\n', ...
                    gen, best_fitness_history(gen), avg_fitness_history(gen));
        end
        
        % 5. 检查终止条件
        if stagnation_counter >= params.stagnation_limit
            fprintf('  提前终止:连续 %d 代无改进\n', stagnation_counter);
            break;
        end
        
        if best_fitness_history(gen) <= params.target_fitness
            fprintf('  提前终止:达到目标适应度\n');
            break;
        end
        
        % 6. 选择操作
        selected_population = selection(population, params);
        
        % 7. 交叉操作
        offspring = crossover(selected_population, params, problem);
        
        % 8. 变异操作
        offspring = mutation(offspring, params, problem);
        
        % 9. 精英保留
        population = elitism(population, offspring, params);
    end
end

%% ========== 遗传算子函数 ==========

function population = evaluate_population(population, problem)
    % 评估种群适应度
    for i = 1:length(population)
        chromosome = population{i};
        
        % 解码并计算Makespan
        [~, makespan] = decode_solution(chromosome, problem);
        
        % 适应度 = 1 / Makespan(最小化Makespan等价于最大化适应度)
        chromosome.fitness = 1 / makespan;
        
        population{i} = chromosome;
    end
end

function selected_population = selection(population, params)
    % 选择操作(锦标赛选择)
    selected_population = cell(params.pop_size, 1);
    
    for i = 1:params.pop_size
        % 随机选择tournament_size个个体
        candidates = randperm(params.pop_size, params.tournament_size);
        best_candidate = candidates(1);
        best_fitness = population{best_candidate}.fitness;
        
        % 选择适应度最好的个体
        for j = 2:params.tournament_size
            candidate = candidates(j);
            if population{candidate}.fitness < best_fitness
                best_candidate = candidate;
                best_fitness = population{candidate}.fitness;
            end
        end
        
        selected_population{i} = population{best_candidate};
    end
end

function offspring = crossover(selected_population, params, problem)
    % 交叉操作(部分映射交叉PMX)
    offspring = cell(params.pop_size, 1);
    
    for i = 1:2:params.pop_size-1
        parent1 = selected_population{i};
        parent2 = selected_population{i+1};
        
        if rand() < params.pc
            % 执行交叉
            [child1, child2] = pmx_crossover(parent1, parent2, problem);
            offspring{i} = child1;
            offspring{i+1} = child2;
        else
            % 不交叉,直接复制
            offspring{i} = parent1;
            offspring{i+1} = parent2;
        end
    end
end

function [child1, child2] = pmx_crossover(parent1, parent2, problem)
    % 部分映射交叉(PMX)
    % 仅对工序顺序进行交叉,机器分配保持不变
    
    % 复制父代
    child1 = parent1;
    child2 = parent2;
    
    % 随机选择交叉点
    point1 = randi([1, problem.total_ops-1]);
    point2 = randi([point1+1, problem.total_ops]);
    
    % 交换中间段
    segment1 = parent1.op_sequence(point1:point2);
    segment2 = parent2.op_sequence(point1:point2);
    
    child1.op_sequence(point1:point2) = segment2;
    child2.op_sequence(point1:point2) = segment1;
    
    % 修复冲突(确保同一工件工序顺序正确)
    child1.op_sequence = repair_sequence(child1.op_sequence, problem);
    child2.op_sequence = repair_sequence(child2.op_sequence, problem);
end

function sequence = repair_sequence(sequence, problem)
    % 修复工序顺序,确保同一工件的工序按顺序排列
    % 简化版:重新生成合法序列
    job_counts = zeros(1, problem.n_jobs);
    new_sequence = zeros(1, length(sequence));
    
    for pos = 1:length(sequence)
        op_code = sequence(pos);
        job_id = floor(op_code / 100);
        op_id = mod(op_code, 100);
        
        % 检查是否合法
        if op_id == job_counts(job_id) + 1
            job_counts(job_id) = job_counts(job_id) + 1;
            new_sequence(pos) = op_code;
        else
            % 不合法,重新分配
            for job = 1:problem.n_jobs
                if job_counts(job) < problem.ops_per_job(job)
                    job_counts(job) = job_counts(job) + 1;
                    new_sequence(pos) = job * 100 + job_counts(job);
                    break;
                end
            end
        end
    end
    
    sequence = new_sequence;
end

function offspring = mutation(offspring, params, problem)
    % 变异操作
    for i = 1:length(offspring)
        chromosome = offspring{i};
        
        % 工序顺序变异
        if rand() < params.pm
            chromosome.op_sequence = mutate_operation_sequence(chromosome.op_sequence, problem);
        end
        
        % 机器分配变异
        if rand() < params.pm
            chromosome.machine_assignment = mutate_machine_assignment(chromosome.op_sequence, problem);
        end
        
        offspring{i} = chromosome;
    end
end

function sequence = mutate_operation_sequence(sequence, problem)
    % 工序顺序变异(交换两个位置)
    pos1 = randi(length(sequence));
    pos2 = randi(length(sequence));
    
    % 确保交换合法
    while pos1 == pos2
        pos2 = randi(length(sequence));
    end
    
    % 交换
    temp = sequence(pos1);
    sequence(pos1) = sequence(pos2);
    sequence(pos2) = temp;
    
    % 修复序列
    sequence = repair_sequence(sequence, problem);
end

function machine_assignment = mutate_machine_assignment(op_sequence, problem)
    % 机器分配变异
    machine_assignment = zeros(1, length(op_sequence));
    
    for pos = 1:length(op_sequence)
        op_code = op_sequence(pos);
        job_id = floor(op_code / 100);
        op_id = mod(op_code, 100);
        
        % 获取可选机器
        machine_options = problem.ops_machine{job_id, op_id};
        n_options = size(machine_options, 1);
        
        % 随机选择一台机器
        selected_option = randi(n_options);
        machine_assignment(pos) = machine_options(selected_option, 1);
    end
end

function population = elitism(population, offspring, params)
    % 精英保留策略
    % 合并父代和子代
    combined_population = [population; offspring];
    
    % 按适应度排序
    fitness_values = zeros(length(combined_population), 1);
    for i = 1:length(combined_population)
        fitness_values(i) = combined_population{i}.fitness;
    end
    
    [~, sorted_indices] = sort(fitness_values);
    
    % 选择前pop_size个
    population = cell(params.pop_size, 1);
    for i = 1:params.pop_size
        population{i} = combined_population{sorted_indices(i)};
    end
end

2.6 解码与调度:decode_solution.m

function [schedule, makespan] = decode_solution(chromosome, problem)
    % 解码染色体并生成调度方案
    
    % 初始化调度表
    schedule = struct();
    schedule.job_completion = zeros(1, problem.n_jobs);  % 工件完成时间
    schedule.machine_available = zeros(1, problem.n_machines);  % 机器可用时间
    schedule.operations = cell(problem.total_ops, 1);  % 工序调度信息
    
    % 按工序顺序解码
    for pos = 1:length(chromosome.op_sequence)
        op_code = chromosome.op_sequence(pos);
        machine_id = chromosome.machine_assignment(pos);
        
        % 解码工序编码
        job_id = floor(op_code / 100);
        op_id = mod(op_code, 100);
        
        % 获取加工时间
        machine_options = problem.ops_machine{job_id, op_id};
        processing_time = 0;
        for k = 1:size(machine_options, 1)
            if machine_options(k, 1) == machine_id
                processing_time = machine_options(k, 2);
                break;
            end
        end
        
        % 计算开始时间
        % 约束1:工件前一道工序完成
        earliest_start_job = schedule.job_completion(job_id);
        
        % 约束2:机器空闲
        earliest_start_machine = schedule.machine_available(machine_id);
        
        % 实际开始时间
        start_time = max(earliest_start_job, earliest_start_machine);
        end_time = start_time + processing_time;
        
        % 更新状态
        schedule.job_completion(job_id) = end_time;
        schedule.machine_available(machine_id) = end_time;
        
        % 记录工序信息
        schedule.operations{pos} = struct(...
            'job_id', job_id, ...
            'op_id', op_id, ...
            'machine_id', machine_id, ...
            'start_time', start_time, ...
            'end_time', end_time, ...
            'processing_time', processing_time);
    end
    
    % 计算最大完工时间
    makespan = max(schedule.job_completion);
end

2.7 结果可视化:visualize_results.m

function visualize_results(schedule, makespan, best_fitness_history, avg_fitness_history, problem)
    % 可视化结果
    
    figure('Name', 'FJSP基因演算法求解结果', 'Color', 'white', 'Position', [100, 100, 1400, 800]);
    
    % 1. 甘特图
    subplot(2,3,1);
    draw_gantt_chart(schedule, problem);
    title('最优调度甘特图');
    
    % 2. 进化曲线
    subplot(2,3,2);
    plot(1:length(best_fitness_history), best_fitness_history, 'b-', 'LineWidth', 2, 'DisplayName', '最佳适应度');
    hold on;
    plot(1:length(avg_fitness_history), avg_fitness_history, 'r--', 'LineWidth', 2, 'DisplayName', '平均适应度');
    xlabel('进化代数'); ylabel('适应度 (1/Makespan)');
    title('基因演算法进化曲线');
    legend('Location', 'best');
    grid on;
    
    % 3. 机器利用率
    subplot(2,3,3);
    machine_utilization = calculate_machine_utilization(schedule, makespan, problem);
    bar(1:problem.n_machines, machine_utilization, 'FaceColor', 'cyan');
    xlabel('机器编号'); ylabel('利用率 (%)');
    title('机器利用率');
    grid on;
    
    % 4. 工件完成时间
    subplot(2,3,4);
    job_completion_times = extract_job_completion_times(schedule, problem);
    barh(1:problem.n_jobs, job_completion_times, 'FaceColor', 'green');
    xlabel('完成时间'); ylabel('工件编号');
    title('工件完成时间');
    grid on;
    
    % 5. 关键路径分析
    subplot(2,3,5);
    critical_path = identify_critical_path(schedule, problem);
    plot_critical_path(critical_path, problem);
    title('关键路径分析');
    
    % 6. 收敛性分析
    subplot(2,3,6);
    convergence_analysis(best_fitness_history);
    title('收敛性分析');
end

function draw_gantt_chart(schedule, problem)
    % 绘制甘特图
    colors = lines(problem.n_machines);
    
    for op_idx = 1:length(schedule.operations)
        op = schedule.operations{op_idx};
        if ~isempty(op)
            % 绘制工序条
            y_pos = op.machine_id - 0.4;
            x_start = op.start_time;
            x_width = op.end_time - op.start_time;
            
            rectangle('Position', [x_start, y_pos, x_width, 0.8], ...
                      'FaceColor', colors(op.machine_id, :), ...
                      'EdgeColor', 'black', 'LineWidth', 0.5);
            
            % 添加标签
            text(x_start + x_width/2, op.machine_id, ...
                 sprintf('J%d-O%d', op.job_id, op.op_id), ...
                 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle', ...
                 'FontSize', 8, 'Color', 'white', 'FontWeight', 'bold');
        end
    end
    
    % 设置坐标轴
    xlabel('时间'); ylabel('机器编号');
    ylim([0.5, problem.n_machines+0.5]);
    yticks(1:problem.n_machines);
    xlim([0, max(schedule.machine_available) * 1.1]);
    grid on;
end

function machine_utilization = calculate_machine_utilization(schedule, makespan, problem)
    % 计算机器利用率
    machine_utilization = zeros(1, problem.n_machines);
    
    for machine_id = 1:problem.n_machines
        busy_time = 0;
        for op_idx = 1:length(schedule.operations)
            op = schedule.operations{op_idx};
            if ~isempty(op) && op.machine_id == machine_id
                busy_time = busy_time + op.processing_time;
            end
        end
        machine_utilization(machine_id) = (busy_time / makespan) * 100;
    end
end

function job_completion_times = extract_job_completion_times(schedule, problem)
    % 提取工件完成时间
    job_completion_times = zeros(1, problem.n_jobs);
    
    for job_id = 1:problem.n_jobs
        last_op_end_time = 0;
        for op_idx = 1:length(schedule.operations)
            op = schedule.operations{op_idx};
            if ~isempty(op) && op.job_id == job_id
                last_op_end_time = max(last_op_end_time, op.end_time);
            end
        end
        job_completion_times(job_id) = last_op_end_time;
    end
end

function critical_path = identify_critical_path(schedule, problem)
    % 识别关键路径
    critical_path = [];
    max_end_time = 0;
    
    for op_idx = 1:length(schedule.operations)
        op = schedule.operations{op_idx};
        if ~isempty(op) && op.end_time > max_end_time
            max_end_time = op.end_time;
            critical_path = [critical_path, op_idx];
        end
    end
end

function plot_critical_path(critical_path, problem)
    % 绘制关键路径
    if isempty(critical_path)
        plot(0, 0, 'o');
        axis off;
        return;
    end
    
    % 简化的关键路径可视化
    path_length = length(critical_path);
    x = 1:path_length;
    y = rand(1, path_length) * problem.n_machines;
    
    plot(x, y, 'r-o', 'LineWidth', 2, 'MarkerSize', 8);
    xlabel('路径步骤'); ylabel('机器编号');
    title('关键路径');
    grid on;
end

function convergence_analysis(fitness_history)
    % 收敛性分析
    % 计算收敛速度
    convergence_gen = find(fitness_history == min(fitness_history), 1, 'last');
    improvement_rate = (fitness_history(1) - fitness_history(end)) / fitness_history(1) * 100;
    
    % 绘制收敛曲线
    plot(1:length(fitness_history), fitness_history, 'b-', 'LineWidth', 2);
    hold on;
    plot(convergence_gen, fitness_history(convergence_gen), 'ro', 'MarkerSize', 10, 'LineWidth', 2);
    
    % 添加注释
    text(convergence_gen, fitness_history(convergence_gen), ...
         sprintf('收敛点\n第%d代', convergence_gen), ...
         'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'right');
    
    xlabel('进化代数'); ylabel('适应度');
    title(sprintf('收敛性分析 (改进率: %.1f%%)', improvement_rate));
    grid on;
end

三、扩展功能模块

3.1 多目标FJSP

function multi_objective_fjsp()
    % 多目标FJSP:最小化Makespan、总流经时间、机器负载均衡
    
    % 目标函数
    objectives = {
        @(schedule) schedule.makespan,           % 目标1:最小化Makespan
        @(schedule) calculate_total_flow_time(schedule), % 目标2:最小化总流经时间
        @(schedule) calculate_load_balance(schedule)     % 目标3:最小化机器负载方差
    };
    
    % 使用NSGA-II算法求解
    pareto_front = nsga2_optimization(objectives, problem, params);
end

3.2 动态FJSP

function dynamic_fjsp()
    % 动态FJSP:机器故障、紧急订单插入
    
    % 事件驱动仿真
    events = {
        struct('time', 50, 'type', 'machine_breakdown', 'machine_id', 2),
        struct('time', 100, 'type', 'urgent_order', 'job_id', 4)
    };
    
    % 实时重调度
    for event = events
        if event.time <= current_time
            % 更新调度方案
            updated_schedule = reschedule(event, current_schedule, problem);
            current_schedule = updated_schedule;
        end
    end
end

参考代码 使用基因演算法解柔性作业车间调度问题 www.youwenfan.com/contentcnu/60168.html

四、应用建议

4.1 参数调优指南

参数 推荐范围 说明
种群大小 50-200 太小易早熟,太大计算慢
交叉概率 0.7-0.9 控制探索能力
变异概率 0.05-0.2 维持多样性
精英比例 0.05-0.2 保护优良基因

4.2 性能优化技巧

% 1. 并行计算加速
parfor gen = 1:params.max_gen
    % 并行评估种群
end

% 2. 混合启发式
% 结合局部搜索(如模拟退火)改进GA解
improved_solution = hybrid_local_search(best_solution, problem);

% 3. 自适应参数
% 根据进化状态调整pc和pm
if diversity < threshold
    pm = pm * 1.5;  % 增加变异率
end

4.3 工业应用注意事项

  1. 实际约束:考虑机器维护、工人休息、物料供应等
  2. 不确定性:加工时间可能有波动,需要鲁棒调度
  3. 实时性:快速响应生产变化,支持动态重调度
  4. 可视化:提供直观的甘特图和报表,方便管理人员决策

 

专注于matlab/simulink,电子电路,编程