Il s'agit d'un problème qui détermine l'horaire de travail des infirmières travaillant dans des établissements médicaux tels que les hôpitaux, et c'est un exemple typique du problème d'horaire des équipes. En raison du travail par quarts compliqué comme le quart de jour, le quart de soir, le quart de nuit et la prise en compte de diverses restrictions, c'est une tâche difficile qui nécessite du travail manuel pour obtenir un horaire ...
journée | Mois | Mois | Mois | Feu | Feu | Feu | eau | eau | eau | bois | bois | bois | Argent | Argent | Argent | sol | sol | sol | journée | journée | journée |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Fuseau horaire | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit |
Employé 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
Employé 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
Employé 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]
Procédons concrètement à la mise en œuvre.
pip install deap
Les spécifications de cet exemple sont les suivantes.
journée | Mois | Mois | Mois | Feu | Feu | Feu | eau | eau | eau | bois | bois | bois | Argent | Argent | Argent | sol | sol | sol | journée | journée | journée |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Fuseau horaire | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit |
Nombre de personnes requis | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 3 | 3 | 2 | 4 | 4 | 2 | 4 | 4 |
Employé 0 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employé 1 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||
Employé 2 | ○ | ○ | ○ | ○ | ○ | ○ | |||||||||||||||
Employé 3 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
Employé 4 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employé 5 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||
Employé 6 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||
Employé 7 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employé 8 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ||||||||||||||
Employé 9 | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
Assurez-vous que votre score augmente suffisamment pour répondre aux contraintes suivantes. Les nombres entre parenthèses sont des poids et représentent la priorité de la contrainte.
class Employee(object):
def __init__(self, no, name, age, manager, wills):
self.no = no
self.name = name
self.age = age
self.manager = manager
#la volonté est le jour_Fuseau horaire. 1 est le matin, 2 est midi, 3 est la nuit.
#Exemple) mon_1 est le lundi matin
self.wills = wills
...
#Seulement le matin
e0 = Employee(0, "Yamada", 40, False, ['mon_1', 'tue_1', 'wed_1', 'thu_1', 'fri_1', 'sat_1', 'sun_1'])
#Lun / mer / ven
e1 = Employee(1, "Suzuki", 21, False, ['mon_1', 'mon_2', 'mon_3', 'wed_1', 'wed_2', 'wed_3','fri_1', 'fri_2', 'fri_3'])
#Uniquement le week-end
e2 = Employee(2, "Sato", 18, False, ['sat_1', 'sat_2', 'sat_3', 'sun_1', 'sun_2', 'sun_3'])
#OK n'importe où
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]
#Classe représentant le décalage
#En interne 3(Matin, jour et nuit) *Le 7*10 personnes=Se compose de taples de 210 dimensions
class Shift(object):
#Définition de haut
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']
#Nombre estimé de personnes dans chaque cadre
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 = []
#Générer des données aléatoires
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
#Différence entre le nombre prévu de personnes et le nombre attribué de personnes
people_count_sub_sum = sum(s.abs_people_between_need_and_actual()) / 210.0
#Nombre d'affectations à des moments où vous ne postulez pas
not_applicated_count = s.not_applicated_assign() / 210.0
#Nombre d'employés avec moins de la moitié du nombre d'affectations
few_work_user = len(s.few_work_user()) / 10.0
#Nombre de cadres sans administrateur
no_manager_box = len(s.no_manager_box()) / 21.0
#Assigné à tous les matins, midi et soirs
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)
poids = (-10.0, -100.0, -1.0, -100.0, -10.0)
(Précisez dans l'ordre) pop = toolbox.population(n=300)
CXPB, MUTPB, NGEN = 0.6, 0.5, 500 #Probabilité de croisement, probabilité de mutation, nombre de boucles dans le calcul de l'évolution
$ python nurse_scheduling_by_ga.py
L'évolution a commencé
Évaluer 300 personnes
--0 génération--
Évaluer 245 personnes
*Paramètre 1
Min 0.242857142857
Max 0.242857142857
Avg 0.242857142857
Std 2.2660056242e-08
*Paramètre 2
Min 0.247619047619
Max 0.247619047619
Avg 0.247619047619
Std 9.49766396283e-09
*Paramètre 3
Min 0.0
Max 0.0
Avg 0.0
Std 0.0
*Paramètre 4
Min 0.142857142857
Max 0.142857142857
Avg 0.142857142857
Std 1.66600046866e-08
*Paramètre 5
Min 0.114285714286
Max 0.114285714286
Avg 0.114285714286
Std 1.19267483008e-08
--1 génération--
Évaluer 235 personnes
*Paramètre 1
Min 0.238095238095
Max 0.238095238095
Avg 0.238095238095
Std 2.45699769971e-08
*Paramètre 2
Min 0.228571428571
Max 0.228571428571
Avg 0.228571428571
Std 2.38534966016e-08
*Paramètre 3
Min 0.1
Max 0.1
Avg 0.1
Std 1.31048702444e-08
*Paramètre 4
Min 0.047619047619
Max 0.047619047619
Avg 0.047619047619
Std 4.46646616171e-09
*Paramètre 5
Min 0.1
Max 0.1
Avg 0.1
Std 1.31048702444e-08
(snip)
--499 générations--
Évaluer 219 personnes
*Paramètre 1
Min 0.0333333333333
Max 0.0333333333333
Avg 0.0333333333333
Std 2.98168707519e-09
*Paramètre 2
Min 0.0714285714286
Max 0.0714285714286
Avg 0.0714285714286
Std 8.33000234328e-09
*Paramètre 3
Min 0.1
Max 0.1
Avg 0.1
Std 1.31048702444e-08
*Paramètre 4
Min 0.0952380952381
Max 0.0952380952381
Avg 0.0952380952381
Std 8.93293232343e-09
*Paramètre 5
Min 0.0428571428571
Max 0.0428571428571
Avg 0.0428571428571
Std 4.56253018749e-09
--Fin d'évolution--
Le meilleur individu: [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
journée | Mois | Mois | Mois | Feu | Feu | Feu | eau | eau | eau | bois | bois | bois | Argent | Argent | Argent | sol | sol | sol | journée | journée | journée | Nombre de missions | Numéro souhaité | Taux d'affectation |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Fuseau horaire | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | Matin | Le midi | Nuit | |||
Nombre de personnes requis | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 3 | 3 | 2 | 4 | 4 | 2 | 4 | 4 | |||
Numéro approuvé | 2 | 3 | 3 | 2 | 3 | 3 | 2 | 3 | 3 | 1 | 2 | 2 | 2 | 3 | 3 | 2 | 4 | 4 | 2 | 4 | 4 | |||
Différence | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
Employé 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% |
Employé 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% |
Employé 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]Employé 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% |
Employé 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]Employé 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% |
Employé 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% |
Employé 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% |
Employé 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]Employé 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% |
Nombre d'administrateurs | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 0 | 1 | 1 | 2 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 2 | 1 |
Recommended Posts