Skip to content

Commit 09a8915

Browse files
committed
Adds implementation for genetic functions
1 parent 33f6086 commit 09a8915

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

geneticFunctions.py

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

0 commit comments

Comments
 (0)