Skip to content

Commit ab96e5c

Browse files
committed
Adds code for simulated annealing metaheuristic method
1 parent 088b7bd commit ab96e5c

File tree

1 file changed

+90
-1
lines changed

1 file changed

+90
-1
lines changed

flowshop.py

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
# -*- coding: utf-8 -*-
33

44
import sys
5+
import time
56
from functools import lru_cache
67
from itertools import permutations
7-
import time
8+
from random import randint, shuffle
9+
810
import numpy as np
911

1012
from geneticFunctions import *
@@ -448,6 +450,93 @@ def genetic_algorithm(self):
448450
t_t = e - s
449451
return seq, schedules, makespan, t_t
450452

453+
def swapTwoJobs(self,seq,pos1,pos2):
454+
seq[pos1], seq[pos2] = seq[pos2], seq[pos1]
455+
return seq
456+
457+
def simulated_annealing(self,Ti = 750,Tf = 2.5 ,alpha = 0.93):
458+
#Number of jobs given
459+
n = self.nb_jobs
460+
# of machines given
461+
m = self.nb_machines
462+
#Initialize the primary seq
463+
default_timer = None
464+
if sys.platform == "win32":
465+
default_timer = time.clock
466+
else:
467+
default_timer = time.time
468+
s = default_timer.__call__()
469+
470+
old_seq = list([ i for i in range(0,n)])
471+
shuffle(old_seq)
472+
new_seq = []
473+
old_makeSpan = self._get_makespan(old_seq,self.data)
474+
new_makeSpan = 0
475+
#The difference between the two makespans
476+
delta_mk1 = 0
477+
#Set of cooling constants
478+
Cc = []
479+
#Initialize the temperature
480+
T = Ti
481+
Tf = Tf
482+
alpha = alpha
483+
# of iterations
484+
N_itr = (np.log(Tf/T)/np.log(alpha))
485+
temp_cycle = 0
486+
while N_itr > 0 :
487+
488+
pos1,pos2 = randint(0,n-1),randint(0,n-1)
489+
new_seq = self.swapTwoJobs(old_seq,pos1,pos2)
490+
new_make_span = self._get_makespan(new_seq,self.data)
491+
delta_mk1 = new_make_span - old_makeSpan
492+
493+
if delta_mk1 <= 0:
494+
old_seq = new_seq
495+
old_makeSpan = new_make_span
496+
N_itr-=1
497+
else :
498+
Aprob = np.exp(-(delta_mk1/T) ** -1)
499+
if Aprob > np.random.uniform():
500+
old_seq = new_seq
501+
old_makeSpan = new_make_span
502+
N_itr -= 1
503+
else :
504+
#The solution is discarded
505+
N_itr -= 1
506+
T = T * (alpha ** temp_cycle)
507+
temp_cycle += 1
508+
509+
# Result Sequence
510+
seq = old_seq
511+
e = default_timer.__call__()
512+
513+
schedules = np.zeros((self.nb_machines, self.nb_jobs), dtype=dict)
514+
# schedule first job alone first
515+
task = {"name": "job_{}".format(
516+
seq[0] + 1), "start_time": 0, "end_time": self.data[0][seq[0]]}
517+
schedules[0][0] = task
518+
for m_id in range(1, self.nb_machines):
519+
start_t = schedules[m_id - 1][0]["end_time"]
520+
end_t = start_t + self.data[m_id][0]
521+
task = {"name": "job_{}".format(
522+
seq[0] + 1), "start_time": start_t, "end_time": end_t}
523+
schedules[m_id][0] = task
524+
525+
for index, job_id in enumerate(seq[1::]):
526+
start_t = schedules[0][index]["end_time"]
527+
end_t = start_t + self.data[0][job_id]
528+
task = {"name": "job_{}".format(
529+
job_id + 1), "start_time": start_t, "end_time": end_t}
530+
schedules[0][index + 1] = task
531+
for m_id in range(1, self.nb_machines):
532+
start_t = max(schedules[m_id][index]["end_time"],
533+
schedules[m_id - 1][index + 1]["end_time"])
534+
end_t = start_t + self.data[m_id][job_id]
535+
task = {"name": "job_{}".format(
536+
job_id + 1), "start_time": start_t, "end_time": end_t}
537+
schedules[m_id][index + 1] = task
538+
t_t = e - s
539+
return seq, schedules, old_makeSpan, t_t
451540

452541
class RandomFlowshop:
453542
"""This module makes an instance of random flowshop problem,

0 commit comments

Comments
 (0)