import random
import matplotlib.pyplot as plt
import numpy as np

from Decode import Decode
from Encode import Encode
from GA import GA
from Instance import *


# 绘制甘特图
def Gantt(Machines):
    M = ['red', 'blue', 'yellow', 'orange', 'green', 'palegoldenrod', 'purple', 'pink', 'Thistle', 'Magenta',
         'SlateBlue', 'RoyalBlue', 'Cyan', 'Aqua', 'floralwhite', 'ghostwhite', 'goldenrod', 'mediumslateblue',
         'navajowhite', 'nawy', 'sandybrown', 'moccasin']
    for i in range(len(Machines)):
        Machine = Machines[i]
        Start_time = Machine.O_start
        End_time = Machine.O_end
        for i_1 in range(len(End_time)):
            plt.barh(i, width=End_time[i_1] - Start_time[i_1], height=0.8, left=Start_time[i_1],
                     color=M[Machine.assigned_task[i_1][0] - 1], edgecolor='black')
            plt.text(x=Start_time[i_1] + (End_time[i_1] - Start_time[i_1]) / 2 - 0.5, y=i,
                     s=Machine.assigned_task[i_1][0])
    plt.yticks(np.arange(len(Machines) + 1), np.arange(1, len(Machines) + 2))
    plt.title('Scheduling Gantt chart')
    plt.ylabel('Machines')
    plt.xlabel('Time(min)')
    plt.savefig('优化后排程方案的甘特图.png')
    plt.show()


if __name__ == '__main__':
    Optimal_fit = 9999  # 最佳适应度（初始化）
    Optimal_CHS = 0  # 最佳适应度对应的基因个体（初始化）
    g = GA()
    e = Encode(Processing_time, g.Pop_size, J, J_num, M_num)
    CHS1 = e.Global_initial()
    CHS2 = e.Random_initial()
    CHS3 = e.Local_initial()
    C = np.vstack((CHS1, CHS2, CHS3))
    Best_fit = []  # 记录适应度在迭代过程中的变化，便于绘图
    for i in range(g.Max_Itertions):
        print("iter_{} start!".format(i))
        Fit = g.fitness(C, J, Processing_time, M_num, O_num)
        Best = C[Fit.index(min(Fit))]
        best_fitness = min(Fit)
        if best_fitness < Optimal_fit:
            Optimal_fit = best_fitness
            Optimal_CHS = Best
            print('iter_{}: new best_fitness = {}'.format(i, best_fitness))
        Best_fit.append(Optimal_fit)  # 始终记录当前最优适应度
        for j in range(len(C)):
            Cafter = []
            if random.random() < g.Pc:
                N_i = random.choice(np.arange(len(C)))
                if random.random() < g.Pv:
                    Cross = g.machine_cross(C[j], C[N_i], O_num)
                else:
                    Cross = g.operation_cross(C[j], C[N_i], O_num, J_num)
                Cafter.append(Cross[0])
                Cafter.append(Cross[1])
                Cafter.append(C[j])
            if random.random() < g.Pm:
                if random.random() < g.Pw:
                    Variance = g.machine_variation(C[j], Processing_time, O_num, J)
                else:
                    Variance = g.operation_variation(C[j], O_num, J_num, J, Processing_time, M_num)
                Cafter.append(Variance)
            if Cafter != []:
                Fit = g.fitness(Cafter, J, Processing_time, M_num, O_num)
                C[j] = Cafter[Fit.index(min(Fit))]

    # 迭代结束后输出最终结果
    print("\n=== 优化结果 ===")
    print("最优适应度 (最少完成时间):", Optimal_fit)

    # 解码最优解并绘制甘特图
    d = Decode(J, Processing_time, M_num)
    final_fitness = d.decode(Optimal_CHS, O_num)
    print("解码验证适应度:", final_fitness)

    # 绘制最优甘特图
    Gantt(d.Machines)

    # 绘制收敛曲线
    x = np.linspace(0, g.Max_Itertions, g.Max_Itertions)
    plt.figure()
    plt.plot(x, Best_fit, '-k')
    plt.title('The maximum completion time of each iteration')
    plt.ylabel('Cmax')
    plt.xlabel('Iteration')
    plt.grid(True)
    plt.savefig('最大完成时间的优化过程.png')
    plt.show()