Ma compréhension de l'histoire.
On a :
- une liste d'employés (où un employé a une string pour l'identifier).
- une liste de jobs (où un job est une paire de dates
- une liste de d'assignations "job→employé" compatibles, créé par les CFF en ignorant les souhait des employés.
Compatibilité 1 : les employés n'acceptent que des jobs deux à deux séparés d'au moins 12h de repos.
Compatibilité 2 : les employés doivent prendre un minimum/maximum d'heures de jobs.
Les employés sont interchangeable, et souhaitent échanger leurs jobs en respectant la compatibilité.
Il y a plein de façon de représenter et résoudre ce problème. Certaines représentation vont rendre certains aspects plus simple et d'autres plus compliqués. Les aspects peuvent être la complexité algorithmique, la possibilité de paralléliser, la facilité pour les employés de formuler leur volonté d'échanges, les compromis sur l'optimalité etc... Comparons un peu ce qu'on peut faire.
Dans la vraie vie, les employés voudront des échanges conditionnels comme par exemple :
- je veux le mardi uniquement si j'obtiens aussi le lundi
- je donne le mardi uniquement si j'ai le lundi (sinon je refuse de donner mon mardi)
- je veux 3 jours consécutifs suivi d'un trou
Ces règles qui s'additionnent aux règles de compatibilités précédentes peuvent rendre les choses considérablement plus compliquées, dans un premier temps on va dire que les employés ne font pas de conditionnel.
Les employés vont demander n'importe quel job dans une fourchette de temps. Ils se foutent de quel job spécifique il s'agit, ils veulent juste des horaires sympas. Ainsi en général il y aura beaucoup de possibilités d'échanges.
Dit autrement, un employé va dire "mardi soir", et ça va sélectionner tous les jobs dans cette région.
À noter une possible complication : peut être que pour garder son lundi qu'il a souhaité conserver, pour pouvoir prendre un mardi, il lui faut impérativement remplacer son lundi par un autre job du lundi.
Il serait bien que l'algo réponde aux souhaits de tout le monde, et n'avantage pas une certaine population.
Peut on tester toutes les combinaisons ? Voici un algo pour tout tester : on regarde toutes les configuration pour job1, puis job2, puis job3, etc... Et on note le meilleur truc qu'on a eu.
Cet algo est bourrin, mais si je ne me trompe pas, parcourt tous les cas possibles d'échanges, et retourne le meilleur, où on a défini meilleur comme étant le schedule qui prend en compte un nombre maximum d'échanges.
Le critère "meilleur" peut être amélioré en disant qu'on veut aussi être égalitaire et maximiser la satisfaction individuelle.
Ça peut se faire en ajoutant une pénalité qui augmente lorsque qu'il y a déséquilibre de satisfaction où on définit satisfaction comme
Cette déviation peut être vue comme
Chaque employé détient une liste de jobs. Il peut les échanger avec un autre employé comme des cartes pokémon : chaque employé liste les jobs qu'il veut bien donner, et les jobs qu'il aimerait recevoir.
Pour se simplifier la vie, on va transformer
Puis les employés déplacent certains de leurs jobs de
Pour gagner en perf, on peut éliminer les wish irréalisables d'office, en comparant avec les give disponibles
On pourrait paralléliser l'algo de ouf avec ce genre d'interaction : chaque thread est un dresseur de pokémons et il discute avec ses collègues.
On peut faire des échanges 1v1
Puis faire une loop
Mais ça va favoriser les premiers qui ont plus de choix (les derniers n'ont que les miettes).
On pourrait prendre toutes les paires possibles, et les mélanger, ou simplement y aller bourrin en prenant des paires au pif
parmis les employés qui ont encore qqch à
On peut gagner en perf en disant qu'il y a des gens qui ont envie de donner ou recevoir, comme ça on évite les échanges entre des employés qui ne seraient que donneur, ou que receveur.
À noter qu'il est quasi-sûr que si le nombre de configuration idéale est rare, on va les louper et rester sur un optimum local. Mais ça a l'avantage de trouver une solution rapidement.
Peut on améliorer ce truc d'optimum local ? Je pense que oui avec une approche "trading". Chaque employé annonce publiquement ce qu'il a à donner, puis il va acheter ce qui lui convient.
Et si à la fin il ne reste des jobs incompatibles, on peut les rendre aux personnes qui y étaient assignés à la base, puis relancer un mega-trade.
Et si la situation finale fait que des gens sont super lésés alors que d'autres super avantagés, on peut faire une restitution aléatoire, ou alors des perquisitions de job chez les plus satisfaits pour compenser les gens le plus lésés.
Par ailleurs, cette analogie de marcé peut servir d'heuristique : par ex utiliser un équivalent de l'argent pour gérer les trades :
- prix = nombre d'heure du job ; budget = nombre d'heure de job qu'il vend
- prix = augmente avec la satisfaction (pour mettre en priorité ceux qui sont les plus lésés)
Comme on s'attend à ce qu'il puisse y avoir beaucoup d'échanges, on peut essayer un algo type annealing, c'est à dire faire des échanges aléatoires, et freeze au fur et à mesure de plus en plus d'assignation correctes.
Pour cela, on peut demander à chaque employé de donner un score d'appréciation à une tranche horaire.
⋅ 0 = je veux
⋅ 0.5 = ça m'est égal
⋅ 1 = je ne veux pas
rédiger l'algo avec la datastructure appropriée