|
2 | 2 | # -*- coding: utf-8 -*- |
3 | 3 |
|
4 | 4 | import numpy as np |
5 | | - |
| 5 | +fromitertoolsimportpermutations |
6 | 6 |
|
7 | 7 | class Flowshop(object): |
8 | 8 | """ |
@@ -84,6 +84,11 @@ def cds(self, parameter_list): |
84 | 84 | raise NotImplementedError |
85 | 85 |
|
86 | 86 | def palmer_heuristic(self): |
| 87 | + """solves an N machines M jobs pfsp problem using Palmer's Heuristic |
| 88 | + |
| 89 | + Returns: |
| 90 | + tuple -- a tuple containing the job sequence, scheduled jobs and optimal makespan. |
| 91 | + """ |
87 | 92 | def palmer_f(x): return -(self.nb_machines - (2*x - 1)) |
88 | 93 | weights = list(map(palmer_f, range(1, self.nb_machines+1))) |
89 | 94 | ws = [] |
@@ -124,6 +129,44 @@ def palmer_f(x): return -(self.nb_machines - (2*x - 1)) |
124 | 129 | opt_makespan = int(schedules[self.nb_machines-1][-1]["end_time"]) |
125 | 130 | return h_seq, schedules, opt_makespan |
126 | 131 |
|
| 132 | + def brute_force_exact(self): |
| 133 | + jobs_perm = permutations(range(self.nb_jobs)) |
| 134 | + opt_makespan = float("inf") |
| 135 | + for seq in jobs_perm: |
| 136 | + schedules = np.zeros((self.nb_machines, self.nb_jobs), dtype=dict) |
| 137 | + # schedule first job alone first |
| 138 | + task = {"name": "job_{}".format( |
| 139 | + seq[0]+1), "start_time": 0, "end_time": self.data[0][seq[0]]} |
| 140 | + schedules[0][0] = task |
| 141 | + for m_id in range(1, self.nb_machines): |
| 142 | + start_t = schedules[m_id-1][0]["end_time"] |
| 143 | + end_t = start_t + self.data[m_id][0] |
| 144 | + task = {"name": "job_{}".format( |
| 145 | + seq[0]+1), "start_time": start_t, "end_time": end_t} |
| 146 | + schedules[m_id][0] = task |
| 147 | + |
| 148 | + for index, job_id in enumerate(seq[1::]): |
| 149 | + start_t = schedules[0][index]["end_time"] |
| 150 | + end_t = start_t + self.data[0][job_id] |
| 151 | + task = {"name": "job_{}".format( |
| 152 | + job_id+1), "start_time": start_t, "end_time": end_t} |
| 153 | + schedules[0][index+1] = task |
| 154 | + for m_id in range(1, self.nb_machines): |
| 155 | + start_t = max(schedules[m_id][index]["end_time"], |
| 156 | + schedules[m_id-1][index+1]["end_time"]) |
| 157 | + end_t = start_t + self.data[m_id][job_id] |
| 158 | + task = {"name": "job_{}".format( |
| 159 | + job_id+1), "start_time": start_t, "end_time": end_t} |
| 160 | + schedules[m_id][index+1] = task |
| 161 | + makespan = int(schedules[self.nb_machines-1][-1]["end_time"]) |
| 162 | + if makespan < opt_makespan: |
| 163 | + opt_makespan = makespan |
| 164 | + best_schedule = np.copy(schedules) |
| 165 | + best_seq = np.copy(seq) |
| 166 | + |
| 167 | + return best_seq, best_schedule, opt_makespan |
| 168 | + |
| 169 | + |
127 | 170 |
|
128 | 171 | class RandomFlowshop: |
129 | 172 | """This module makes an instance of random flowshop problem, |
@@ -195,10 +238,13 @@ def get_problem_instance(self): |
195 | 238 |
|
196 | 239 |
|
197 | 240 | if __name__ == "__main__": |
198 | | - random_problem = RandomFlowshop(3, 3) |
| 241 | + random_problem = RandomFlowshop(5, 5) |
199 | 242 | random_problem_instance = random_problem.get_problem_instance() |
200 | | - seq, scheds = random_problem_instance.palmer_heuristic() |
201 | | - print(scheds) |
| 243 | + seq, scheds, opt_makespan = random_problem_instance.palmer_heuristic() |
| 244 | + b_seq, b_scheds, b_opt_makespan = random_problem_instance.brute_force_exact() |
| 245 | + |
| 246 | + print("Brute Force: {}, Palmer heuristic: {}".format(b_opt_makespan, opt_makespan)) |
| 247 | + |
202 | 248 | #seq, jobs, opt_makespan = random_problem_instance.solve_johnson() |
203 | 249 | # print("Sequence: {} \nJobs on Machine 1: \n {} \n Jobs on machine 2:\n {} \n".format( |
204 | 250 | # seq, jobs[0], jobs[1])) |
0 commit comments