Spaces:
Runtime error
Runtime error
Commit ·
b75af81
0
Parent(s):
Duplicate from GowriHari/OptimizationJSSP
Browse files- .gitattributes +34 -0
- Demo_data.xlsx +0 -0
- GA.py +299 -0
- MIP.py +133 -0
- OR_tools.py +148 -0
- README.md +14 -0
- app.py +55 -0
- requirements.txt +28 -0
.gitattributes
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
Demo_data.xlsx
ADDED
|
Binary file (10.3 kB). View file
|
|
|
GA.py
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# importing required modules
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
import chart_studio.plotly as py
|
| 6 |
+
import plotly.figure_factory as ff
|
| 7 |
+
import datetime
|
| 8 |
+
from datetime import timedelta
|
| 9 |
+
import time
|
| 10 |
+
import copy
|
| 11 |
+
import openpyxl as xl
|
| 12 |
+
import json
|
| 13 |
+
|
| 14 |
+
'''Defining Functions for GA Algorithm'''
|
| 15 |
+
def input_file(input):
|
| 16 |
+
data = data_excel_json(input)
|
| 17 |
+
op,img,schedule_df = job_schedule(data_dict=data)
|
| 18 |
+
return op,img,schedule_df
|
| 19 |
+
|
| 20 |
+
def data_excel_json(excel_sheet):
|
| 21 |
+
""" convert excel into json """
|
| 22 |
+
data_excel = xl.load_workbook(excel_sheet)
|
| 23 |
+
data = {}
|
| 24 |
+
sheet_name = data_excel.sheetnames
|
| 25 |
+
for sheet in sheet_name:
|
| 26 |
+
wb_sheet = data_excel[sheet]
|
| 27 |
+
cell_values = wb_sheet.values
|
| 28 |
+
df = pd.DataFrame(cell_values, columns=next(cell_values))
|
| 29 |
+
df.iloc[:, 0] = df.iloc[:, 0].apply(lambda x : x.strip())
|
| 30 |
+
df.index = df.iloc[:, 0]
|
| 31 |
+
df.drop(columns = df.columns[0], inplace=True)
|
| 32 |
+
data[sheet] = df.T.to_dict()
|
| 33 |
+
#print("function - data_excel_json: ", data)
|
| 34 |
+
return data
|
| 35 |
+
|
| 36 |
+
def json_to_df(json_data):
|
| 37 |
+
""" convert json into excel """
|
| 38 |
+
dict_data = {}
|
| 39 |
+
for key in json_data.keys():
|
| 40 |
+
dict_data[key] = pd.DataFrame(json_data.get(key)).T
|
| 41 |
+
#print("function - json_to_df: ", dict_data)
|
| 42 |
+
return dict_data
|
| 43 |
+
|
| 44 |
+
def generate_initial_population(population_size, num_gene):
|
| 45 |
+
|
| 46 |
+
""" generate initial population for Genetic Algorithm """
|
| 47 |
+
|
| 48 |
+
best_list, best_obj = [], []
|
| 49 |
+
population_list = []
|
| 50 |
+
makespan_record = []
|
| 51 |
+
for i in range(population_size):
|
| 52 |
+
nxm_random_num = list(np.random.permutation(num_gene)) # generate a random permutation of 0 to num_job*num_mc-1
|
| 53 |
+
population_list.append(nxm_random_num) # add to the population_list
|
| 54 |
+
for j in range(num_gene):
|
| 55 |
+
population_list[i][j] = population_list[i][j] % num_job # convert to job number format, every job appears m times
|
| 56 |
+
#print("function - generate_initial_population: ", population_list)
|
| 57 |
+
|
| 58 |
+
return population_list
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def job_schedule(data_dict, population_size = 30, crossover_rate = 0.8, mutation_rate = 0.2, mutation_selection_rate = 0.2, num_iteration = 3000):
|
| 63 |
+
|
| 64 |
+
""" initialize genetic algorithm parameters and read data """
|
| 65 |
+
data_json = json_to_df(data_dict)
|
| 66 |
+
#print(data_json)
|
| 67 |
+
machine_sequence_tmp = data_json['Machines Sequence']
|
| 68 |
+
process_time_tmp = data_json['Processing Time']
|
| 69 |
+
# print("Machine_sequence_tmp: ",machine_sequence_tmp)
|
| 70 |
+
# print("Processing_time_tmp: ",process_time_tmp)
|
| 71 |
+
|
| 72 |
+
df_shape = process_time_tmp.shape
|
| 73 |
+
num_machines = df_shape[1] # number of machines
|
| 74 |
+
num_job = df_shape[0] # number of jobs
|
| 75 |
+
num_gene = num_machines * num_job # number of genes in a chromosome
|
| 76 |
+
num_mutation_jobs = round(num_gene * mutation_selection_rate)
|
| 77 |
+
|
| 78 |
+
process_time = [list(map(int, process_time_tmp.iloc[i])) for i in range(num_job)]
|
| 79 |
+
machine_sequence = [list(map(int, machine_sequence_tmp.iloc[i])) for i in range(num_job)]
|
| 80 |
+
|
| 81 |
+
#start_time = time.time()
|
| 82 |
+
|
| 83 |
+
Tbest = 999999999999999
|
| 84 |
+
|
| 85 |
+
best_list, best_obj = [], []
|
| 86 |
+
population_list = []
|
| 87 |
+
makespan_record = []
|
| 88 |
+
|
| 89 |
+
for i in range(population_size):
|
| 90 |
+
nxm_random_num = list(np.random.permutation(num_gene)) # generate a random permutation of 0 to num_job*num_mc-1
|
| 91 |
+
population_list.append(nxm_random_num) # add to the population_list
|
| 92 |
+
for j in range(num_gene):
|
| 93 |
+
population_list[i][j] = population_list[i][j] % num_job # convert to job number format, every job appears m times
|
| 94 |
+
#population_list = generate_initial_population(population_size=population_size, num_gene=num_gene)
|
| 95 |
+
|
| 96 |
+
for iteration in range(num_iteration):
|
| 97 |
+
Tbest_now = 99999999999
|
| 98 |
+
|
| 99 |
+
""" Two Point Cross-Over """
|
| 100 |
+
parent_list = copy.deepcopy(population_list)
|
| 101 |
+
offspring_list = copy.deepcopy(population_list) # generate a random sequence to select the parent chromosome to crossover
|
| 102 |
+
pop_random_size = list(np.random.permutation(population_size))
|
| 103 |
+
|
| 104 |
+
for size in range(int(population_size/2)):
|
| 105 |
+
crossover_prob = np.random.rand()
|
| 106 |
+
if crossover_rate >= crossover_prob:
|
| 107 |
+
parent_1 = population_list[pop_random_size[2*size]][:]
|
| 108 |
+
parent_2 = population_list[pop_random_size[2*size+1]][:]
|
| 109 |
+
|
| 110 |
+
child_1 = parent_1[:]
|
| 111 |
+
child_2 = parent_2[:]
|
| 112 |
+
cutpoint = list(np.random.choice(num_gene, 2, replace=False))
|
| 113 |
+
cutpoint.sort()
|
| 114 |
+
|
| 115 |
+
child_1[cutpoint[0]:cutpoint[1]] = parent_2[cutpoint[0]:cutpoint[1]]
|
| 116 |
+
child_2[cutpoint[0]:cutpoint[1]] = parent_1[cutpoint[0]:cutpoint[1]]
|
| 117 |
+
offspring_list[pop_random_size[2*size]] = child_1[:]
|
| 118 |
+
offspring_list[pop_random_size[2*size+1]] = child_2[:]
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
for pop in range(population_size):
|
| 122 |
+
|
| 123 |
+
""" Repairment """
|
| 124 |
+
job_count = {}
|
| 125 |
+
larger, less = [], [] # 'larger' record jobs appear in the chromosome more than pop times, and 'less' records less than pop times.
|
| 126 |
+
for job in range(num_job):
|
| 127 |
+
if job in offspring_list[pop]:
|
| 128 |
+
count = offspring_list[pop].count(job)
|
| 129 |
+
pos = offspring_list[pop].index(job)
|
| 130 |
+
job_count[job] = [count, pos] # store the above two values to the job_count dictionary
|
| 131 |
+
else:
|
| 132 |
+
count = 0
|
| 133 |
+
job_count[job] = [count, 0]
|
| 134 |
+
|
| 135 |
+
if count > num_machines:
|
| 136 |
+
larger.append(job)
|
| 137 |
+
elif count < num_machines:
|
| 138 |
+
less.append(job)
|
| 139 |
+
|
| 140 |
+
for large in range(len(larger)):
|
| 141 |
+
change_job = larger[large]
|
| 142 |
+
while job_count[change_job][0] > num_machines:
|
| 143 |
+
for les in range(len(less)):
|
| 144 |
+
if job_count[less[les]][0] < num_machines:
|
| 145 |
+
offspring_list[pop][job_count[change_job][1]] = less[les]
|
| 146 |
+
job_count[change_job][1] = offspring_list[pop].index(change_job)
|
| 147 |
+
job_count[change_job][0] = job_count[change_job][0]-1
|
| 148 |
+
job_count[less[les]][0] = job_count[less[les]][0]+1
|
| 149 |
+
if job_count[change_job][0] == num_machines:
|
| 150 |
+
break
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
for off_spring in range(len(offspring_list)):
|
| 155 |
+
|
| 156 |
+
""" Mutations """
|
| 157 |
+
mutation_prob = np.random.rand()
|
| 158 |
+
if mutation_rate >= mutation_prob:
|
| 159 |
+
m_change = list(np.random.choice(num_gene, num_mutation_jobs, replace=False)) # chooses the position to mutation
|
| 160 |
+
t_value_last = offspring_list[off_spring][m_change[0]] # save the value which is on the first mutation position
|
| 161 |
+
for i in range(num_mutation_jobs-1):
|
| 162 |
+
offspring_list[off_spring][m_change[i]] = offspring_list[off_spring][m_change[i+1]] # displacement
|
| 163 |
+
# move the value of the first mutation position to the last mutation position
|
| 164 |
+
offspring_list[off_spring][m_change[num_mutation_jobs-1]] = t_value_last
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
""" fitness value (calculate makespan) """
|
| 169 |
+
total_chromosome = copy.deepcopy(parent_list) + copy.deepcopy(offspring_list) # parent and offspring chromosomes combination
|
| 170 |
+
chrom_fitness, chrom_fit = [], []
|
| 171 |
+
total_fitness = 0
|
| 172 |
+
for pop_size in range(population_size*2):
|
| 173 |
+
j_keys = [j for j in range(num_job)]
|
| 174 |
+
key_count = {key:0 for key in j_keys}
|
| 175 |
+
j_count = {key:0 for key in j_keys}
|
| 176 |
+
m_keys = [j+1 for j in range(num_machines)]
|
| 177 |
+
m_count = {key:0 for key in m_keys}
|
| 178 |
+
|
| 179 |
+
for i in total_chromosome[pop_size]:
|
| 180 |
+
gen_t = int(process_time[i][key_count[i]])
|
| 181 |
+
gen_m = int(machine_sequence[i][key_count[i]])
|
| 182 |
+
j_count[i] = j_count[i] + gen_t
|
| 183 |
+
m_count[gen_m] = m_count[gen_m] + gen_t
|
| 184 |
+
|
| 185 |
+
if m_count[gen_m] < j_count[i]:
|
| 186 |
+
m_count[gen_m] = j_count[i]
|
| 187 |
+
elif m_count[gen_m] > j_count[i]:
|
| 188 |
+
j_count[i] = m_count[gen_m]
|
| 189 |
+
|
| 190 |
+
key_count[i] = key_count[i] + 1
|
| 191 |
+
|
| 192 |
+
makespan = max(j_count.values())
|
| 193 |
+
chrom_fitness.append(1/makespan)
|
| 194 |
+
chrom_fit.append(makespan)
|
| 195 |
+
total_fitness = total_fitness + chrom_fitness[pop_size]
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
""" Selection (roulette wheel approach) """
|
| 199 |
+
pk, qk = [], []
|
| 200 |
+
|
| 201 |
+
for size in range(population_size * 2):
|
| 202 |
+
pk.append(chrom_fitness[size] / total_fitness)
|
| 203 |
+
for size in range(population_size * 2):
|
| 204 |
+
cumulative = 0
|
| 205 |
+
|
| 206 |
+
for j in range(0, size+1):
|
| 207 |
+
cumulative = cumulative + pk[j]
|
| 208 |
+
qk.append(cumulative)
|
| 209 |
+
|
| 210 |
+
selection_rand = [np.random.rand() for i in range(population_size)]
|
| 211 |
+
|
| 212 |
+
for pop_size in range(population_size):
|
| 213 |
+
if selection_rand[pop_size] <= qk[0]:
|
| 214 |
+
population_list[pop_size] = copy.deepcopy(total_chromosome[0])
|
| 215 |
+
else:
|
| 216 |
+
for j in range(0, population_size * 2-1):
|
| 217 |
+
if selection_rand[pop_size] > qk[j] and selection_rand[pop_size] <= qk[j+1]:
|
| 218 |
+
population_list[pop_size] = copy.deepcopy(total_chromosome[j+1])
|
| 219 |
+
break
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
""" comparison """
|
| 223 |
+
for pop_size in range(population_size * 2):
|
| 224 |
+
if chrom_fit[pop_size] < Tbest_now:
|
| 225 |
+
Tbest_now = chrom_fit[pop_size]
|
| 226 |
+
sequence_now = copy.deepcopy(total_chromosome[pop_size])
|
| 227 |
+
if Tbest_now <= Tbest:
|
| 228 |
+
Tbest = Tbest_now
|
| 229 |
+
sequence_best = copy.deepcopy(sequence_now)
|
| 230 |
+
|
| 231 |
+
makespan_record.append(Tbest)
|
| 232 |
+
|
| 233 |
+
""" Results - Makespan """
|
| 234 |
+
|
| 235 |
+
print("optimal sequence", sequence_best)
|
| 236 |
+
print("optimal value:%f"%Tbest)
|
| 237 |
+
print("\n")
|
| 238 |
+
#print('the elapsed time:%s'% (time.time() - start_time))
|
| 239 |
+
op = "Optimal Schedule Length :"+str(Tbest)
|
| 240 |
+
#%matplotlib inline
|
| 241 |
+
plt.plot([i for i in range(len(makespan_record))],makespan_record,'b')
|
| 242 |
+
plt.ylabel('makespan', fontsize=15)
|
| 243 |
+
plt.xlabel('generation', fontsize=15)
|
| 244 |
+
plt.show()
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
""" plot gantt chart """
|
| 248 |
+
|
| 249 |
+
m_keys = [j+1 for j in range(num_machines)]
|
| 250 |
+
j_keys = [j for j in range(num_job)]
|
| 251 |
+
key_count = {key:0 for key in j_keys}
|
| 252 |
+
j_count = {key:0 for key in j_keys}
|
| 253 |
+
m_count = {key:0 for key in m_keys}
|
| 254 |
+
j_record = {}
|
| 255 |
+
for i in sequence_best:
|
| 256 |
+
gen_t = int(process_time[i][key_count[i]])
|
| 257 |
+
gen_m = int(machine_sequence[i][key_count[i]])
|
| 258 |
+
j_count[i] = j_count[i] + gen_t
|
| 259 |
+
m_count[gen_m] = m_count[gen_m] + gen_t
|
| 260 |
+
|
| 261 |
+
if m_count[gen_m] < j_count[i]:
|
| 262 |
+
m_count[gen_m] = j_count[i]
|
| 263 |
+
elif m_count[gen_m] > j_count[i]:
|
| 264 |
+
j_count[i] = m_count[gen_m]
|
| 265 |
+
|
| 266 |
+
start_time = str(datetime.timedelta(seconds = j_count[i] - process_time[i][key_count[i]])) # convert seconds to hours, minutes and seconds
|
| 267 |
+
end_time = str(datetime.timedelta(seconds = j_count[i]))
|
| 268 |
+
|
| 269 |
+
j_record[(i, gen_m)] = [start_time, end_time]
|
| 270 |
+
|
| 271 |
+
key_count[i] = key_count[i] + 1
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
df = []
|
| 275 |
+
for m in m_keys:
|
| 276 |
+
for j in j_keys:
|
| 277 |
+
df.append(dict(Task='Machine %s'%(m), Start='2020-02-01 %s'%(str(j_record[(j,m)][0])), \
|
| 278 |
+
Finish='2020-02-01 %s'%(str(j_record[(j,m)][1])),Resource='Job %s'%(j+1)))
|
| 279 |
+
|
| 280 |
+
df_data = pd.DataFrame(df)
|
| 281 |
+
df_ = pd.DataFrame(df)
|
| 282 |
+
df_.Start = pd.to_datetime(df_['Start'])
|
| 283 |
+
df_.Finish = pd.to_datetime(df_['Finish'])
|
| 284 |
+
start = df_.Start.min()
|
| 285 |
+
end = df_.Finish.max()
|
| 286 |
+
|
| 287 |
+
df_.Start = df_.Start.apply(lambda x: x.strftime('%Y-%m-%dT%H:%M:%S'))
|
| 288 |
+
df_.Finish = df_.Finish.apply(lambda x: x.strftime('%Y-%m-%dT%H:%M:%S'))
|
| 289 |
+
data = df_.to_dict('record')
|
| 290 |
+
|
| 291 |
+
final_data ={
|
| 292 |
+
'start':start.strftime('%Y-%m-%dT%H:%M:%S'),
|
| 293 |
+
'end':end.strftime('%Y-%m-%dT%H:%M:%S'),
|
| 294 |
+
'data':data}
|
| 295 |
+
|
| 296 |
+
fig = ff.create_gantt(df, index_col='Resource', show_colorbar=True, group_tasks=True, showgrid_x=True, title='Job shop Schedule')
|
| 297 |
+
|
| 298 |
+
#iplot(fig, filename='GA_job_shop_scheduling')
|
| 299 |
+
return op, fig, df_data
|
MIP.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# importing required modules
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
import pandas as pd
|
| 6 |
+
import chart_studio.plotly as py
|
| 7 |
+
import plotly.figure_factory as ff
|
| 8 |
+
import datetime
|
| 9 |
+
from datetime import timedelta
|
| 10 |
+
import time
|
| 11 |
+
import copy
|
| 12 |
+
|
| 13 |
+
#importing PuLP solver
|
| 14 |
+
import pulp
|
| 15 |
+
from itertools import product
|
| 16 |
+
|
| 17 |
+
def gantt_for_MIP(df,method):
|
| 18 |
+
title_chart = 'Job shop Schedule - using '+ method
|
| 19 |
+
fig = ff.create_gantt(df, index_col='Resource', show_colorbar=True, group_tasks=True, showgrid_x=True, title=title_chart)
|
| 20 |
+
return fig
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def MIP_fn(input_file):
|
| 24 |
+
xls = pd.ExcelFile(input_file)
|
| 25 |
+
df1 = pd.read_excel(xls, 'Machines Sequence',index_col = 0)
|
| 26 |
+
df2 = pd.read_excel(xls, 'Processing Time',index_col = 0)
|
| 27 |
+
|
| 28 |
+
times =[]
|
| 29 |
+
machines = []
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
for ind in df1.index:
|
| 33 |
+
list_m = []
|
| 34 |
+
list_t = []
|
| 35 |
+
for col in df1:
|
| 36 |
+
list_m.append(df1[col][ind]-1) # for MIP formulation
|
| 37 |
+
list_t.append(df2[col][ind])
|
| 38 |
+
times.append(list_t)
|
| 39 |
+
machines.append(list_m)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
pt = df2.values
|
| 43 |
+
mo = df1.values-1 # for the numbering the machines from 0 to 9
|
| 44 |
+
|
| 45 |
+
m=n=len(pt[0])
|
| 46 |
+
print("The number of machines and jobs in the given input data is - ",m)
|
| 47 |
+
|
| 48 |
+
#Max time possible for all the jobs - summation of all the process time
|
| 49 |
+
M = sum(times[i][j] for i in range(n) for j in range(m))
|
| 50 |
+
|
| 51 |
+
model = pulp.LpProblem("MIN_makespan", pulp.LpMinimize)
|
| 52 |
+
|
| 53 |
+
dv = pulp.LpVariable.dicts("start_time",
|
| 54 |
+
((i, j) for i in range(m) for j in range(n)),
|
| 55 |
+
lowBound=0,
|
| 56 |
+
cat='Continuous')
|
| 57 |
+
#print(dv)
|
| 58 |
+
b = pulp.LpVariable.dicts("binary_var",
|
| 59 |
+
((j, k, i) for i in range(m) for k in range(n) for j in range(n)),
|
| 60 |
+
lowBound=0,
|
| 61 |
+
cat='Binary')
|
| 62 |
+
# print(b)
|
| 63 |
+
Cmax = pulp.LpVariable('Cmax',lowBound = 0, cat='Continuous')
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
# (1) operation sequence inside a job
|
| 67 |
+
model += Cmax
|
| 68 |
+
for j in range(m):
|
| 69 |
+
for i in range(n-1):
|
| 70 |
+
I = mo[j,i]
|
| 71 |
+
K = mo[j,i+1]
|
| 72 |
+
J = j
|
| 73 |
+
|
| 74 |
+
model += (dv[J,K] - dv[J,I]) >= pt[J][list(mo[J]).index(I)]
|
| 75 |
+
# print((dv[J,K] - dv[J,I]) >= pt[J][list(mo[J]).index(I)])
|
| 76 |
+
|
| 77 |
+
# (2) the max start time
|
| 78 |
+
for j in range(m):
|
| 79 |
+
for i in range(n):
|
| 80 |
+
|
| 81 |
+
I = mo[j,i]
|
| 82 |
+
J = j
|
| 83 |
+
model += (Cmax - dv[J,I]) >= pt[J][list(mo[J]).index(I)]
|
| 84 |
+
#print((Cmax - dv[J,I]) >= pt[J][list(mo[J]).index(I)])
|
| 85 |
+
|
| 86 |
+
# (3) no overlap for operations assigned to same machine
|
| 87 |
+
for (j, k) in product(range(n), range(n)):
|
| 88 |
+
if k != j:
|
| 89 |
+
for i in range(m):
|
| 90 |
+
model += dv[j,i] - dv[k,i] + M*b[j,k,i] >= pt[k][list(mo[k]).index(i)]
|
| 91 |
+
model += -dv[j,i] + dv[k,i] - M*b[j,k,i] >= pt[j][list(mo[j]).index(i)] - M
|
| 92 |
+
|
| 93 |
+
start_time = time.time()
|
| 94 |
+
model.solve(pulp.PULP_CBC_CMD(timeLimit=200))
|
| 95 |
+
print("Solution status : ",pulp.LpStatus[model.status])
|
| 96 |
+
|
| 97 |
+
# for var in dv:
|
| 98 |
+
# var_value = dv[var].varValue
|
| 99 |
+
# print( var[0],'-',var[1] ,var_value)
|
| 100 |
+
|
| 101 |
+
tota_time = pulp.value(model.objective)
|
| 102 |
+
print ('Optimal time:',tota_time)
|
| 103 |
+
print('Solver processing time:%s'% (time.time() - start_time))
|
| 104 |
+
op = "Optimal Schedule Length :"+ str(tota_time)
|
| 105 |
+
|
| 106 |
+
m_keys=[j for j in range(m)]
|
| 107 |
+
j_keys=[j for j in range(n)]
|
| 108 |
+
key_count={key:0 for key in j_keys}
|
| 109 |
+
j_count={key:0 for key in j_keys}
|
| 110 |
+
m_count={key:0 for key in m_keys}
|
| 111 |
+
j_record={}
|
| 112 |
+
|
| 113 |
+
for var in dv:
|
| 114 |
+
var_value = dv[var].varValue
|
| 115 |
+
|
| 116 |
+
start_time=str(datetime.timedelta(seconds=var_value)) # convert seconds to hours, minutes and seconds
|
| 117 |
+
end_time=str(datetime.timedelta(seconds=var_value+pt[var[1]][list(mo[var[1]]).index(var[0])]))
|
| 118 |
+
|
| 119 |
+
j_record[(var[1],var[0])]=[start_time,end_time]
|
| 120 |
+
|
| 121 |
+
key_count[i]=key_count[i]+1
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
df=[]
|
| 125 |
+
for m in m_keys:
|
| 126 |
+
for j in j_keys:
|
| 127 |
+
df.append(dict(Task='Machine %s'%(m), Start='2020-02-01 %s'%(str(j_record[(j,m)][0])), Finish='2020-02-01 %s'%(str(j_record[(j,m)][1])),Resource='Job %s'%(j)))
|
| 128 |
+
|
| 129 |
+
method = 'PuLP - CBC Solver'
|
| 130 |
+
df_data = pd.DataFrame(df)
|
| 131 |
+
|
| 132 |
+
return op,gantt_for_MIP(df,method),df_data
|
| 133 |
+
|
OR_tools.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# importing required modules
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
import pandas as pd
|
| 6 |
+
import chart_studio.plotly as py
|
| 7 |
+
import plotly.figure_factory as ff
|
| 8 |
+
import datetime
|
| 9 |
+
from datetime import timedelta
|
| 10 |
+
import time
|
| 11 |
+
import copy
|
| 12 |
+
|
| 13 |
+
#importing OR-tools solver
|
| 14 |
+
import collections
|
| 15 |
+
from ortools.sat.python import cp_model
|
| 16 |
+
|
| 17 |
+
def gantt_for_OR(df,method):
|
| 18 |
+
title_chart = 'Job shop Schedule - using '+ method
|
| 19 |
+
fig = ff.create_gantt(df, index_col='Resource', show_colorbar=True, group_tasks=True, showgrid_x=True, title=title_chart)
|
| 20 |
+
return fig
|
| 21 |
+
|
| 22 |
+
def or_fn(input_file):
|
| 23 |
+
xls = pd.ExcelFile(input_file)
|
| 24 |
+
df1 = pd.read_excel(xls, 'Machines Sequence',index_col = 0)
|
| 25 |
+
df2 = pd.read_excel(xls, 'Processing Time',index_col = 0)
|
| 26 |
+
|
| 27 |
+
jobs_data =[]
|
| 28 |
+
|
| 29 |
+
for ind in df1.index:
|
| 30 |
+
lists = []
|
| 31 |
+
for col in df1:
|
| 32 |
+
lists.append((df1[col][ind],df2[col][ind]))
|
| 33 |
+
jobs_data.append(lists)
|
| 34 |
+
|
| 35 |
+
model = cp_model.CpModel()
|
| 36 |
+
machines_count = 1 + max(task[0] for job in jobs_data for task in job)
|
| 37 |
+
all_machines = range(machines_count)
|
| 38 |
+
# Computes horizon dynamically as the sum of all durations.
|
| 39 |
+
horizon = sum(task[1] for job in jobs_data for task in job)
|
| 40 |
+
|
| 41 |
+
# Named tuple to store information about created variables.
|
| 42 |
+
task_type = collections.namedtuple('task_type', 'start end interval')
|
| 43 |
+
# Named tuple to manipulate solution information.
|
| 44 |
+
assigned_task_type = collections.namedtuple('assigned_task_type',
|
| 45 |
+
'start job index duration')
|
| 46 |
+
|
| 47 |
+
# Creates job intervals and add to the corresponding machine lists.
|
| 48 |
+
all_tasks = {}
|
| 49 |
+
machine_to_intervals = collections.defaultdict(list)
|
| 50 |
+
|
| 51 |
+
for job_id, job in enumerate(jobs_data):
|
| 52 |
+
for task_id, task in enumerate(job):
|
| 53 |
+
machine = task[0]
|
| 54 |
+
duration = task[1]
|
| 55 |
+
suffix = '_%i_%i' % (job_id, task_id)
|
| 56 |
+
start_var = model.NewIntVar(0, horizon, 'start' + suffix)
|
| 57 |
+
end_var = model.NewIntVar(0, horizon, 'end' + suffix)
|
| 58 |
+
interval_var = model.NewIntervalVar(start_var, duration, end_var,
|
| 59 |
+
'interval' + suffix)
|
| 60 |
+
all_tasks[job_id, task_id] = task_type(start=start_var,
|
| 61 |
+
end=end_var,
|
| 62 |
+
interval=interval_var)
|
| 63 |
+
machine_to_intervals[machine].append(interval_var)
|
| 64 |
+
|
| 65 |
+
# Create and add disjunctive constraints.
|
| 66 |
+
for machine in all_machines:
|
| 67 |
+
model.AddNoOverlap(machine_to_intervals[machine])
|
| 68 |
+
|
| 69 |
+
# Precedences inside a job.
|
| 70 |
+
for job_id, job in enumerate(jobs_data):
|
| 71 |
+
for task_id in range(len(job) - 1):
|
| 72 |
+
model.Add(all_tasks[job_id, task_id +
|
| 73 |
+
1].start >= all_tasks[job_id, task_id].end)
|
| 74 |
+
|
| 75 |
+
# Makespan objective.
|
| 76 |
+
obj_var = model.NewIntVar(0, horizon, 'makespan')
|
| 77 |
+
model.AddMaxEquality(obj_var, [
|
| 78 |
+
all_tasks[job_id, len(job) - 1].end
|
| 79 |
+
for job_id, job in enumerate(jobs_data)
|
| 80 |
+
])
|
| 81 |
+
model.Minimize(obj_var)
|
| 82 |
+
|
| 83 |
+
start_time = time.time()
|
| 84 |
+
|
| 85 |
+
solver = cp_model.CpSolver()
|
| 86 |
+
status = solver.Solve(model)
|
| 87 |
+
|
| 88 |
+
print("--- %s seconds ---" % (time.time() - start_time))
|
| 89 |
+
|
| 90 |
+
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
|
| 91 |
+
print('Solution:')
|
| 92 |
+
# Create one list of assigned tasks per machine.
|
| 93 |
+
assigned_jobs = collections.defaultdict(list)
|
| 94 |
+
for job_id, job in enumerate(jobs_data):
|
| 95 |
+
for task_id, task in enumerate(job):
|
| 96 |
+
machine = task[0]
|
| 97 |
+
assigned_jobs[machine].append(
|
| 98 |
+
assigned_task_type(start=solver.Value(
|
| 99 |
+
all_tasks[job_id, task_id].start),
|
| 100 |
+
job=job_id,
|
| 101 |
+
index=task_id,
|
| 102 |
+
duration=task[1]))
|
| 103 |
+
|
| 104 |
+
# Create per machine output lines.
|
| 105 |
+
output = ''
|
| 106 |
+
for machine in all_machines:
|
| 107 |
+
# Sort by starting time.
|
| 108 |
+
assigned_jobs[machine].sort()
|
| 109 |
+
sol_line_tasks = 'Machine ' + str(machine) + ': '
|
| 110 |
+
sol_line = ' '
|
| 111 |
+
|
| 112 |
+
for assigned_task in assigned_jobs[machine]:
|
| 113 |
+
name = 'job_%i_task_%i' % (assigned_task.job,
|
| 114 |
+
assigned_task.index)
|
| 115 |
+
# Add spaces to output to align columns.
|
| 116 |
+
sol_line_tasks += '%-15s' % name
|
| 117 |
+
|
| 118 |
+
start = assigned_task.start
|
| 119 |
+
duration = assigned_task.duration
|
| 120 |
+
sol_tmp = '[%i,%i]' % (start, start + duration)
|
| 121 |
+
# Add spaces to output to align columns.
|
| 122 |
+
sol_line += '%-15s' % sol_tmp
|
| 123 |
+
|
| 124 |
+
sol_line += '\n'
|
| 125 |
+
sol_line_tasks += '\n'
|
| 126 |
+
output += sol_line_tasks
|
| 127 |
+
output += sol_line
|
| 128 |
+
|
| 129 |
+
# Finally print the solution found.
|
| 130 |
+
print(f'Optimal Schedule Length: {solver.ObjectiveValue()}')
|
| 131 |
+
op = "Optimal Schedule Length : "+ str(solver.ObjectiveValue())
|
| 132 |
+
#print(output)
|
| 133 |
+
else:
|
| 134 |
+
print('No solution found.')
|
| 135 |
+
op = "No solution found."
|
| 136 |
+
#Solution df:
|
| 137 |
+
df = []
|
| 138 |
+
for machine in all_machines:
|
| 139 |
+
for task in assigned_jobs[machine]:
|
| 140 |
+
df.append(dict(Task='Machine %s'%(machine), Start='2020-02-01 %s'%(str(timedelta(seconds=int(task[0])))), \
|
| 141 |
+
Finish='2020-02-01 %s'%(str(timedelta(seconds=int(task[0]+task[3])))),Resource='Job %s'%(task[1])))
|
| 142 |
+
|
| 143 |
+
method = 'OR Tools'
|
| 144 |
+
fig = gantt_for_OR(df,method)
|
| 145 |
+
fig.show()
|
| 146 |
+
df_data = pd.DataFrame(df)
|
| 147 |
+
|
| 148 |
+
return op,gantt_for_OR(df,method),df_data
|
README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: OptimizationJSSP
|
| 3 |
+
emoji: 🌍
|
| 4 |
+
colorFrom: pink
|
| 5 |
+
colorTo: pink
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 3.29.0
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
duplicated_from: GowriHari/OptimizationJSSP
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# importing required modules
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
import datetime
|
| 6 |
+
from datetime import timedelta
|
| 7 |
+
import time
|
| 8 |
+
import copy
|
| 9 |
+
import openpyxl as xl
|
| 10 |
+
import json
|
| 11 |
+
import gradio as gr
|
| 12 |
+
import io
|
| 13 |
+
from PIL import Image
|
| 14 |
+
|
| 15 |
+
#importing 3 functions:
|
| 16 |
+
import GA
|
| 17 |
+
import OR_tools as ort
|
| 18 |
+
import MIP
|
| 19 |
+
|
| 20 |
+
def plotly_fig2array(fig):
|
| 21 |
+
#convert Plotly fig to an array
|
| 22 |
+
fig_bytes = fig.to_image(format="png")
|
| 23 |
+
buf = io.BytesIO(fig_bytes)
|
| 24 |
+
img = Image.open(buf)
|
| 25 |
+
return np.asarray(img)
|
| 26 |
+
|
| 27 |
+
def JSSP(method,temp_file):
|
| 28 |
+
xls = pd.ExcelFile(temp_file.name)
|
| 29 |
+
print(xls)
|
| 30 |
+
print("Input File is :",xls)
|
| 31 |
+
if method == "Genetic Algo":
|
| 32 |
+
op, fig, df = GA.input_file(xls)
|
| 33 |
+
|
| 34 |
+
elif method == "Python OR":
|
| 35 |
+
op, fig, df = ort.or_fn(xls)
|
| 36 |
+
|
| 37 |
+
else:
|
| 38 |
+
op, fig, df = MIP.MIP_fn(xls)
|
| 39 |
+
|
| 40 |
+
img = plotly_fig2array(fig)
|
| 41 |
+
# data = pd.DataFrame(df)
|
| 42 |
+
df.to_excel("op_data.xlsx",index=False)
|
| 43 |
+
data_op = ["op_data.xlsx"]
|
| 44 |
+
return op, img,data_op
|
| 45 |
+
|
| 46 |
+
demo = gr.Interface(JSSP,
|
| 47 |
+
inputs=[gr.Radio(["Genetic Algo", "Python OR", "MIP solution"], label="Solution Method", info="Choose one method to solve ypur Job Shop problem."),gr.File(label = 'Input File')],
|
| 48 |
+
examples =[["Python OR","Demo_data.xlsx"]],
|
| 49 |
+
outputs = ["text","image",gr.File(label='Output File')],
|
| 50 |
+
title = "Job Shop Scheduling Problem",
|
| 51 |
+
description = "Upload an excel file containing Machine Sequnce and Processing Time for a n x m problem to optimize makespan for manufacturing or Job schedule. Choose the method you want the problem to be solved before clicking Submit! \n For Demo purpose, use the example data provided BELOW.",
|
| 52 |
+
cache_examples = False )
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
demo.queue().launch(debug=True,show_error=True)
|
requirements.txt
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
chart-studio==1.1.0
|
| 2 |
+
convertdate==2.4.0
|
| 3 |
+
gradio==3.32.0
|
| 4 |
+
gradio_client==0.2.5
|
| 5 |
+
jsonpickle==3.0.1
|
| 6 |
+
jsonschema==4.3.3
|
| 7 |
+
matplotlib==3.7.1
|
| 8 |
+
matplotlib-inline==0.1.6
|
| 9 |
+
matplotlib-venn==0.11.9
|
| 10 |
+
more-itertools==9.1.0
|
| 11 |
+
numpy==1.22.4
|
| 12 |
+
openpyxl==3.0.10
|
| 13 |
+
orjson==3.8.12
|
| 14 |
+
ortools==9.6.2534
|
| 15 |
+
pandas==1.5.3
|
| 16 |
+
pandas-datareader==0.10.0
|
| 17 |
+
pandas-gbq==0.17.9
|
| 18 |
+
plotly==5.13.1
|
| 19 |
+
PuLP==2.7.0
|
| 20 |
+
python-dateutil==2.8.2
|
| 21 |
+
python-utils==3.5.2
|
| 22 |
+
scikit-image==0.19.3
|
| 23 |
+
scikit-learn==1.2.2
|
| 24 |
+
scipy==1.10.1
|
| 25 |
+
seaborn==0.12.2
|
| 26 |
+
sklearn-pandas==2.2.0
|
| 27 |
+
kaleido
|
| 28 |
+
pillow
|