-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathgeneticFunctions.py
More file actions
108 lines (96 loc) · 4.35 KB
/
geneticFunctions.py
File metadata and controls
108 lines (96 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# -*-coding:utf-8 -*
import os
import random
import time
from functools import reduce
import numpy as np
def calc_makespan(solution, proccessing_time, number_of_jobs, number_of_machines):
# list for the time passed until the finishing of the job
cost = [0] * number_of_jobs
# for each machine, total time passed will be updated
for machine_no in range(0, number_of_machines):
for slot in range(number_of_jobs):
# time passed so far until the task starts to process
cost_so_far = cost[slot]
if slot > 0:
cost_so_far = max(cost[slot - 1], cost[slot])
cost[slot] = cost_so_far + proccessing_time[solution[slot]][machine_no]
return cost[number_of_jobs - 1]
def initialize_population(population_size, number_of_jobs):
population = []
i = 0
while i < population_size:
individual = list(np.random.permutation(number_of_jobs))
if individual not in population:
population.append(individual)
i += 1
return population
# Two-point crossover is that the set of jobs between
# two randomly selected points is always inherited from one parent to the child,
# and the other jobs are placed in the same manner as the one-point crossover.
def crossover(parents):
parent1 = parents[0]
parent2 = parents[1]
length_of_parent = len(parent1)
first_point = int(length_of_parent / 2 - length_of_parent / 4)
second_point = int(length_of_parent - first_point)
intersect = parent1[first_point:second_point]
child = []
index = 0
for pos2 in range(len(parent2)):
if first_point <= index < second_point:
child.extend(intersect)
index = second_point
if parent2[pos2] not in intersect:
child.append(parent2[pos2])
index += 1
return child
# apply mutation to an existing solution using swap move operator
def mutation(solution):
# copy the solution
mutated_solution = list(solution)
solution_length = len(solution)
# pick 2 positions to swap randomly
swap_positions = list(np.random.permutation(np.arange(solution_length))[:2])
first_job = solution[swap_positions[0]]
second_job = solution[swap_positions[1]]
mutated_solution[swap_positions[0]] = second_job
mutated_solution[swap_positions[1]] = first_job
return mutated_solution
# Selects parent by binary tournament method
def select_parent(population, processing_time, number_of_jobs, number_of_machines):
parent_pairs = []
# randomly choose how many parent pairs will be selected
parent_pair_count = random.randint(2, int(len(population)/2))
for k in range(parent_pair_count):
parent1 = binary_tournament(number_of_jobs, number_of_machines, population, processing_time)
parent2 = binary_tournament(number_of_jobs, number_of_machines, population, processing_time)
if parent1 != parent2 and (parent1, parent2) not in parent_pairs:
parent_pairs.append((parent1, parent2))
return parent_pairs
def binary_tournament(number_of_jobs, number_of_machines, population, processing_time):
parent = []
candidates = random.sample(population, 2)
makespan1 = calc_makespan(candidates[0], processing_time, number_of_jobs, number_of_machines)
makespan2 = calc_makespan(candidates[1], processing_time, number_of_jobs, number_of_machines)
if makespan1 < makespan2:
parent = candidates[0]
else:
parent = candidates[1]
return parent
def update_population(population, children,processing_time,no_of_jobs,no_of_machines):
costed_population = []
for individual in population:
ind_makespan = (calc_makespan(individual, processing_time, no_of_jobs, no_of_machines), individual)
costed_population.append(ind_makespan)
costed_population.sort(key=lambda x: x[0], reverse=True)
costed_children = []
for individual in children:
ind_makespan = (calc_makespan(individual, processing_time, no_of_jobs, no_of_machines), individual)
costed_children.append(ind_makespan)
costed_children.sort(key=lambda x: x[0])
for child in costed_children:
if child not in population:
population.append(individual)
population.remove(costed_population[0][1])
break