|
2 | 2 | # -*- coding: utf-8 -*- |
3 | 3 |
|
4 | 4 | import sys |
| 5 | +import time |
5 | 6 | from functools import lru_cache |
6 | 7 | from itertools import permutations |
7 | | -import time |
| 8 | +from random import randint, shuffle |
| 9 | + |
8 | 10 | import numpy as np |
9 | 11 |
|
10 | 12 | from geneticFunctions import * |
@@ -448,6 +450,93 @@ def genetic_algorithm(self): |
448 | 450 | t_t = e - s |
449 | 451 | return seq, schedules, makespan, t_t |
450 | 452 |
|
| 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 |
451 | 540 |
|
452 | 541 | class RandomFlowshop: |
453 | 542 | """This module makes an instance of random flowshop problem, |
|
0 commit comments