-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenetics.py
executable file
·131 lines (102 loc) · 4.63 KB
/
genetics.py
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""
Author: Corneel den Hartogh
Course: Heuristics
Description: Genetic algorithm code
"""
from operator import itemgetter
import copy
import random
import time
from csvFilesController import classrooms,subjects,students
from classes import Classroom,Subject,Activity,Student,Roster
from scoreFunction import getScore
from studentOptimization import studentOptimization
from roomOptimization import roomOptimization
from reproduction import reproduceTimeOrDay, reproduceSubjects
def genetics():
startTime = time.process_time()
rosterPopulation = []
# get a random population of 20
while len(rosterPopulation) < 20:
newRoster = Roster(classrooms,subjects, students)
newRoster.fillInRoster()
score = getScore(newRoster)
rosterPopulation.append([newRoster, score])
scores = []
scores.append(rosterPopulation[19][1])
iteration = 0
# after a cycle of length 'period' we check if there was still progress
while len(scores) == 1 or scores[-1] > scores[-2]:
t = 0
period = 1000
# number of generations
while t < period:
# two parents are gathered from the population of 30 and two children are made
parents = random.sample(range(20), 2)
father = rosterPopulation[parents[0]][0]
mother = rosterPopulation[parents[1]][0]
childOne = Roster(classrooms,subjects, students)
childTwo = Roster(classrooms,subjects, students)
child = [childOne, childTwo]
for c in range(2):
timetable = {}
first = None
second = None
if c == 0:
first = father
second = mother
else:
first = mother
second = father
# what type of reproduction is exectued?
case = random.randint(0,2)
if case == 0:
day = random.randint(1,4)
timeSlot = 0
reproductionResult = reproduceTimeOrDay(timetable, day,timeSlot, first, second, child[c].activities, len(classrooms))
if case == 1:
day = 0
timeSlot = random.randint(1,3)
reproductionResult = reproduceTimeOrDay(timetable, day,timeSlot, first, second, child[c].activities, len(classrooms))
if case == 2:
reproductionResult = reproduceSubjects(timetable, first, second, child[c].activities, len(classrooms))
child[c].timetable = reproductionResult[0]
child[c].activities = reproductionResult[1]
# repair if necessary, if parents are complementary ensure mutation
mutationNeed = 0
for activity in child[c].activities:
if activity.slot == ():
child[c].getSlot()
while child[c].slot in child[c].timetable:
child[c].getSlot()
child[c].timetable[child[c].slot] = activity
activity.slot = child[c].slot
else:
mutationNeed +=1
if mutationNeed > 126:
mutations = random.sample(range(129), mutationNeed - 126)
for mut in range(len(mutations)):
activity = child[c].activities[mutations[mut]]
del timetable[activity.slot]
child[c].getSlot()
while child[c].slot in child[c].timetable:
child[c].getSlot()
child[c].timetable[child[c].slot] = activity
activity.slot = child[c].slot
# make sure students are sorted appropriately over the WorkLectures and Practica
# this enhancement seemed to add 50-100 to the score (which was stable over generations)
child[c] = studentOptimization(child[c])
child[c] = roomOptimization(child[c])
score = getScore(child[c])
# add child to population
rosterPopulation.append([child[c], score])
# delete the unfittest two rosters from the populations
rosterPopulation.sort(key=itemgetter(1))
del rosterPopulation[0:2]
t += 1
scores.append(rosterPopulation[19][1])
iteration += 1
# export best roster
runtime = time.process_time() - startTime
rosterPopulation[19][0].exportRoster("genetics",rosterPopulation[19][1],runtime)
genetics()