车间调度问题

问题描述 六工四机问题

一个车间有四台机器,要求加工6个作业

分工序,每个机器加工不同的工序

M1 M2 M3 M4
J1 8 4 5 3
J2 2 6 5 6
J3 12 5 4 2
J4 4 1 4 9
J5 6 2 7 3
J6 5 6 9 3

遗传算法基本步骤

步骤1:选择编码策略,将实际问题的参数集合X表示位串。
步骤2:根据实际问题的优化目标,定义适应度值函数。
步骤3:确定遗传策略,包括群体大小n、选择、交叉、变异操作的方法,确定交叉概率Pc,变异概率Pm等参数。
步骤4:产生初始群体P。
步骤5:计算群体中所有个体的适应度值。
步骤6:按照遗传策略,对群体中的每一个个体选择、复制、交叉、变异操作,形成下一代群体。
步骤6:判断群体性能是否满足终止条件,不满足则返回第6步,进行下一次迭代;满足条件则完成计算,输出结果。

主要内容:编码→确定规则→跑算法→输出

import random  # 产生随机数
# pop是种群,二元组(可行解的总完成时间,编码列表)
pop = [(ComputeStartTimes(g, I)[-1], g) for g in InitPopulation(ps, I)]
mit = input("迭代次数")
for it in range(1, mit+1):
    random.shuffle(pop)  # 随机打乱pop中的个体
    hpop = len(pop)/2  # hpop是种群的一半
    for i in range(hpop):
        if random() < 0.3:  # 交叉概率
            # 通过交叉生成两个新元素
            ch1 = Crossover(pop[i][1], pop[hpop+i][1], I)
            ch2 = Crossover(pop[hpop+i][1], pop[i][1], I)
            if random() < 0.1:  # 如果变异概率小于0.1
                ch1 = Mutation(ch1)
            if random() < 0.1:
                ch2 = Mutation(ch2)
            pop.append((ComputeStartTimes(ch1, I)[-1], ch1))  # 将两个新解放回种群
            pop.append((ComputeStartTimes(ch2, I)[-1], ch2))
            # 按时间跨度顺序进行排序并选择出优胜者
            pop.sort()
            pop = pop[:ps]
    return pop[0]  # 返回完成时间最小的染色体

主要函数

自文件中读入instance对象中

def LoadInstance(fname):
    f = open(fname, 'r')"""打开配置文件 Init.txt"""
    head = f.readline().split()"""读入第一行"""
    n, m = int(head[0]), int(head[1])"""将工件数和机器数存在n和m两个变量中"""
    I = []""" 构造上文中的“jobs列表”"""
    for l in f:"""从文件中依次读入每行数据,一行对应一个工件"""
        l = l.split()
        if len(l) < 3: continue """如果少于3个数则跳过该行"""
        ntasks = int(l[0])"""ntasks存放该工件包含的工序道数,Init每行对应一个工件""""
        I.append([])"""每行一个子list代表一个工件的信息"""
        for j in range(ntasks):
            mid = int(l[j*2+1])
            dur = int(l[j*2+2])
            I[-1].append((mid, dur))"""每个工件有多道工序,每个工序对应一个有序偶(机器数,加工时间)"""
    return Instance(I, m)"""返回Instance类的一个实例"""

class Instance:
    """Class representing an instance of the JSP."""
    def __init__(self, jobs, m):
        self.jobs = jobs
        self.n = len(jobs) # number of jobs
        self.m = m         # number of machines

    def __getitem__(self, i):
        return self.jobs[i]

    def __len__(self):
        return len(self.jobs)

交叉

def Crossover(p1, p2, I)://p1,p2是两条待交叉的染色体,I存放工序和工件的信息(见编码部分)
        """Crossover operation for the GA. Generalized Order Crossover (GOX)."""
        def Index(p1, I)://这个函数接收两个参数p1和I,返回p1对应的有序偶list,n存储的是工件总数
            ct = [0 for j in range(n)]
            s = []
            for i in p1:
                s.append((i, ct[i]))
                ct[i] = ct[i] + 1
            return s
        idx_p1 = Index(p1, I) //p1的有序偶list,p1即上文的Parent2
        idx_p2 = Index(p2, I) //p2的有序偶list,p2即上文的Parent1
        nt = len(idx_p1) //p1的有序偶list的长度
        i = randint(1, nt-1)//1到nt-1间的随机数
        j = randint(0, nt-1)//0 到nt-1间的随机数
        k = randint(0, nt-1)//k为Parent1插入Parent2时的插入点位置
         //implant 相当于上面的“(A,2)(C,1)(A,3)(B,3)”即从Parent1抽取的片段
        implant = idx_p1[j:min(j+i,nt)] + idx_p1[:i - min(j+i,nt) + j]
        lft_child = idx_p2[:k]
        rgt_child = idx_p2[k:]
        for jt in implant://从Parent1删除与插入片段重复的有序偶
            if jt in lft_child: lft_child.remove(jt)
            if jt in rgt_child: rgt_child.remove(jt)
        //Child:即相当于BABACABCCB
        child = [ job for (job, task) in lft_child + implant + rgt_child ]
        return child

变异

def Mutation(p)://p是解的编码
        nt = len(p)//nt存放染色体的长度
        i = randint(0, nt - 1)//i是0到nt-1之间的一个随机数
        j = randint(0, nt - 1)//j是0到nt-1之间的一个随机数
        m = [job for job in p]//将解p复制到临时变量m中
        m[i], m[j] = m[j], m[i]//交换m中i和j位置的值
        return m//返回m

输出结果

def FormatSolution(s, C, I):
    T = [0 for j in range(n)]
    S = [[0 for t in I[j]] for j in range(n)]//n存储的是工件总数
    for i in range(len(s)):"""遍历染色体"""
        j = s[i]"""获得i的工件号j """
        t = T[j]"""获得i是j的第几道工序t"""
        S[j][t] = C[i]"""将i的加工时间存到S的相应位置中"""
        T[j] = T[j] + 1"""工件j的工序累加器+1 """
    return S

C语言的深度搜索方法

#include <stdio.h>
#include <string.h>
#include <algorithm> #调用memset函数
using namespace std;
int totalStep, minTime;
int n, m;
int Step[105];
struct Job #工作
{
    int machine;
#在哪一台机器 int len;
#工作时长
}
job[105][105];
int jobEnd[105][105];
int jobStep[105]; //步骤
int machineWorkTime[105];
struct Recording
{
    int start;
    int ed;
    int job;
    int machine;
} best[105], now[105];
void init() #初始化
{
    totalStep = 0;
#总计步骤 minTime = 999999999;
    memset(jobStep, 0, sizeof(jobStep));
#将数字拷贝到内存中 memset(machineWorkTime, 0, sizeof(machineWorkTime));
    memset(best, 0, sizeof(best));
    memset(jobEnd, -1, sizeof(jobEnd));
}
void dfs(int step, int time) #深度搜索主函数
{
    if (time >= minTime) //越界
        return;
    if (step == totalStep) //终止条件
    {
        minTime = time;
        for (int i = 0; i < totalStep; i++)
            best[i] = now[i];
        return;
    }

    for (int i = 0; i < n; i++)
    {
        int j = jobStep[i];
        if (j >= Step[i]) //没有访问过
            continue;
        int thisMachine = job[i][j].machine;
        now[step].machine = thisMachine;
        now[step].job = i + 1;
        int temp = machineWorkTime[thisMachine];
        int beginTime = max(jobEnd[i][j - 1], machineWorkTime[thisMachine]);
        now[step].start = beginTime;
        machineWorkTime[thisMachine] = beginTime + job[i][j].len;
        jobEnd[i][j] = now[step].ed = machineWorkTime[thisMachine];
        jobStep[i]++; //标记已经访问
        dfs(step + 1, max(time, machineWorkTime[thisMachine]));
        jobStep[i]--;
        machineWorkTime[thisMachine] = temp;
    }
}
int main()
{
    printf("输入工作数量:");
    scanf("%d", &n);
    printf("输入机器数量:");
    scanf("%d", &m);
    init();
    for (int i = 1; i <= n; i++)
    {
        printf("输入工作%d的步骤数量:", i);
        scanf("%d", &Step[i]);
        totalStep += Step[i];
        for (int j = 0; j < Step[i]; j++)
        {
            printf("    步骤%d运行于第%d台机器所消耗时间:", j + 1, i);
            scanf("%d", &job[i][j].len);
        }
    }
    dfs(0, 0);
    printf("最短时间为:%d\n", minTime);

    int gantt[105][105];
    for (int i = 0; i < totalStep; i++)
    {
        for (int j = best[i].start; j < best[i].ed; j++)
        {
            gantt[best[i].machine][j] = best[i].job;
        }
    }

    for (int i = 0; i < m; i++)
        for (int j = 0; j < minTime; j++)
            printf("%d%c", gantt[i][j], j == minTime - 1 ? '\n' : ' ');
}
posted @   W-xzg  阅读(217)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
1 2 3
4
点击右上角即可分享
微信分享提示