This is a problem of determining the work schedule of nurses working in medical facilities such as hospitals, and is a typical example of the shift scheduling problem. Due to complicated shift work such as day shift, evening shift, night shift, and consideration of various restrictions, it is a difficult task that requires manual labor to actually obtain a schedule ...
Day of the week | Month | Month | Month | fire | fire | fire | water | water | water | wood | wood | wood | Money | Money | Money | soil | soil | soil | Day | Day | Day |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Time zone | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night |
Employee 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
Employee 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
Employee 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
[0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0]
Let's proceed with the implementation concretely.
pip install deap
The specifications of this sample are as follows.
Day of the week | Month | Month | Month | fire | fire | fire | water | water | water | wood | wood | wood | Money | Money | Money | soil | soil | soil | Day | Day | Day |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Time zone | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night |
Required number of people | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 3 | 3 | 2 | 4 | 4 | 2 | 4 | 4 |
Employee 0 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employee 1 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||
Employee 2 | ○ | ○ | ○ | ○ | ○ | ○ | |||||||||||||||
Employee 3 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
Employee 4 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employee 5 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||
Employee 6 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||
Employee 7 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employee 8 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employee 9 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
Make sure your score goes up enough to meet the following constraints. The numbers in parentheses are weights and represent the priority of the constraint.
class Employee(object):
def __init__(self, no, name, age, manager, wills):
self.no = no
self.name = name
self.age = age
self.manager = manager
#will is the day of the week_Time zone. 1 is morning, 2 is noon, 3 is night.
#Example) mon_1 is monday morning
self.wills = wills
...
#Only in the morning
e0 = Employee(0, "Yamada", 40, False, ['mon_1', 'tue_1', 'wed_1', 'thu_1', 'fri_1', 'sat_1', 'sun_1'])
#Mon / Wed / Fri
e1 = Employee(1, "Suzuki", 21, False, ['mon_1', 'mon_2', 'mon_3', 'wed_1', 'wed_2', 'wed_3','fri_1', 'fri_2', 'fri_3'])
#Only on weekends
e2 = Employee(2, "Sato", 18, False, ['sat_1', 'sat_2', 'sat_3', 'sun_1', 'sun_2', 'sun_3'])
#OK anywhere
e3 = Employee(3, "Tanaka", 35, True, ['mon_1', 'mon_2', 'mon_3',
'tue_1', 'tue_2', 'tue_3',
'wed_1', 'wed_2', 'wed_3',
'thu_1', 'thu_2', 'thu_3',
'fri_1', 'fri_2', 'fri_3',
'sat_1', 'sat_2', 'sat_3',
'sun_1', 'sun_2', 'sun_3'
])
...
employees = [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9]
#Class representing shift
#Internally 3(Morning day and night) *The 7th*10 people=Consists of 210-dimensional tuples
class Shift(object):
#Definition of top
SHIFT_BOXES = [
'mon_1', 'mon_2', 'mon_3',
'tue_1', 'tue_2', 'tue_3',
'wed_1', 'wed_2', 'wed_3',
'thu_1', 'thu_2', 'thu_3',
'fri_1', 'fri_2', 'fri_3',
'sat_1', 'sat_2', 'sat_3',
'sun_1', 'sun_2', 'sun_3']
#Estimated number of people in each frame
NEED_PEOPLE = [
2,3,3,
2,3,3,
2,3,3,
1,2,2,
2,3,3,
2,4,4,
2,4,4]
def __init__(self, list):
if list == None:
self.make_sample()
else:
self.list = list
self.employees = []
#Generate random data
def make_sample(self):
sample_list = []
for num in range(210):
sample_list.append(random.randint(0, 1))
self.list = tuple(sample_list)
...
creator.create("FitnessPeopleCount", base.Fitness, weights=(-10.0, -100.0, -1.0, -100.0, -10.0))
creator.create("Individual", list, fitness=creator.FitnessPeopleCount)
...
def evalShift(individual):
s = Shift(individual)
s.employees = employees
#Difference between expected number of people and assigned number of people
people_count_sub_sum = sum(s.abs_people_between_need_and_actual()) / 210.0
#Number of assignments to times when you are not applying
not_applicated_count = s.not_applicated_assign() / 210.0
#Number of employees with less than half the number of assignments
few_work_user = len(s.few_work_user()) / 10.0
#Number of frames with no administrator
no_manager_box = len(s.no_manager_box()) / 21.0
#Assigned to all morning, noon, and night
three_box_per_day = len(s.three_box_per_day()) / 70.0
return (not_applicated_count, people_count_sub_sum, few_work_user, no_manager_box, three_box_per_day)
toolbox.register("evaluate", evalShift)
Return (not_applicated_count, people_count_sub_sum, few_work_user, no_manager_box, three_box_per_day)` `` weights = (-10.0, -100.0, -1.0, -100.0, -10.0)
(Specify in order) pop = toolbox.population(n=300)
CXPB, MUTPB, NGEN = 0.6, 0.5, 500 #Crossing probability, mutation probability, evolutionary computation loop count
$ python nurse_scheduling_by_ga.py
Evolution started
Evaluate 300 individuals
--0 generation--
Evaluate 245 individuals
*Parameter 1
Min 0.242857142857
Max 0.242857142857
Avg 0.242857142857
Std 2.2660056242e-08
*Parameter 2
Min 0.247619047619
Max 0.247619047619
Avg 0.247619047619
Std 9.49766396283e-09
*Parameter 3
Min 0.0
Max 0.0
Avg 0.0
Std 0.0
*Parameter 4
Min 0.142857142857
Max 0.142857142857
Avg 0.142857142857
Std 1.66600046866e-08
*Parameter 5
Min 0.114285714286
Max 0.114285714286
Avg 0.114285714286
Std 1.19267483008e-08
--1 generation--
Evaluate 235 individuals
*Parameter 1
Min 0.238095238095
Max 0.238095238095
Avg 0.238095238095
Std 2.45699769971e-08
*Parameter 2
Min 0.228571428571
Max 0.228571428571
Avg 0.228571428571
Std 2.38534966016e-08
*Parameter 3
Min 0.1
Max 0.1
Avg 0.1
Std 1.31048702444e-08
*Parameter 4
Min 0.047619047619
Max 0.047619047619
Avg 0.047619047619
Std 4.46646616171e-09
*Parameter 5
Min 0.1
Max 0.1
Avg 0.1
Std 1.31048702444e-08
(snip)
--499 generations--
Evaluate 219 individuals
*Parameter 1
Min 0.0333333333333
Max 0.0333333333333
Avg 0.0333333333333
Std 2.98168707519e-09
*Parameter 2
Min 0.0714285714286
Max 0.0714285714286
Avg 0.0714285714286
Std 8.33000234328e-09
*Parameter 3
Min 0.1
Max 0.1
Avg 0.1
Std 1.31048702444e-08
*Parameter 4
Min 0.0952380952381
Max 0.0952380952381
Avg 0.0952380952381
Std 8.93293232343e-09
*Parameter 5
Min 0.0428571428571
Max 0.0428571428571
Avg 0.0428571428571
Std 4.56253018749e-09
--End of evolution--
The best individual: [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1], (0.0, 0.0, 0.2, 0.047619047619047616, 0.1)
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0
0,1,0,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1
1,0,1,0,1,1,0,0,1,0,1,0,1,0,1,0,1,1,0,0,1
0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0
1,1,1,1,1,1,1,1,1,0,0,1,0,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1
0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0
0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 1 0 0 1 0 1 0 1 0 1 0 1 1
0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0
1 1 1 1 1 1 1 1 1 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1
0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1
Day of the week | Month | Month | Month | fire | fire | fire | water | water | water | wood | wood | wood | Money | Money | Money | soil | soil | soil | Day | Day | Day | Number of assignments | Desired number | Assignment rate |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Time zone | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | Morning | Noon | Night | |||
Required number of people | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 3 | 3 | 2 | 4 | 4 | 2 | 4 | 4 | |||
Approved number | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 3 | 3 | 2 | 4 | 4 | 2 | 4 | 4 | |||
Difference | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
Employee 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 5 | 7 | 71.4% |
Employee 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 6 | 9 | 66.7% |
Employee 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 4 | 6 | 66.7% |
[tube]Employee 3 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 7 | 21 | 33.3% |
Employee 4 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 5 | 7 | 71.4% |
[tube]Employee 5 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 8 | 15 | 53.3% |
Employee 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 5 | 9 | 55.6% |
Employee 7 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 6 | 7 | 85.7% |
Employee 8 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 4 | 7 | 57.1% |
[tube]Employee 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 7 | 12 | 58.3% |
Number of administrators | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 0 | 1 | 1 | 2 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 2 | 1 |
Recommended Posts