Je suis un professeur de pratiques de laboratoire à l'université, sur la base des commentaires des étudiants de l'année dernière, nous voulions, mon patron et moi, y répondre. Mon patron a choisi d'aller avec l'écriture d'un script C et je choisis python (python-constraint) pour essayer de résoudre notre problème.
Les informations
- Il y a 6 séances
- Il y a 4 rôles
- Il y a 6 pratiques
- Il y a 32 étudiants
- Il y a 4 étudiants par équipe
Problème:
Attribuez à chaque élève 4 rôles, dans 4 pratiques en 4 sessions différentes.
Contraintes :
- Les étudiants devraient jouer un rôle une fois
- Les étudiants doivent faire 4 pratiques différentes sur 6
- Les étudiants ne doivent faire qu'une seule pratique par session
- L'élève ne doit rencontrer le même compagnon qu'une seule fois
Modèles:
Voici le modèle que je ressens avec les étudiants, où chaque équipe est composée de 4 étudiants, les postes [0, 1, 2 ou 3] sont des rôles qui leur sont assignés. Chaque poste disponible est numéroté de 1 à 128
[# Semester
[ # Session
[ # Practice/Team
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]]]
En d'autres termes :
Ceci est une session:
[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]],
Ces équipes font la même pratique:
[
[1, 2, 3, 4],
[25, 26, 27, 28],
[49, 50, 51, 52],
[73, 74, 75, 76],
[97, 98, 99, 100],
[113, 114, 115, 116]
]
Ces positions jouent le même rôle:
[
1,
5,
9,
13,
17,
21,
25,
...
]
Ce que j'ai jusqu'à présent:
En utilisant python-constraint, j'ai pu valider les trois premières contraintes:
Valid solution : False
- sessions : [True, True, True, True, True, True]
- practices : [True, True, True, True, True, True]
- roles : [True, True, True, True]
- teams : [False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False]
Pour ceux qui peuvent être intéressants, je fais simplement ceci:
Pour chaque condition, j'utilise AllDifferentConstraint . Par exemple, pour une session, je fais:
problem.addConstraint(AllDifferentConstraint(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])
Je ne suis pas en mesure de trouver un moyen de contraindre l'équipe, ma dernière tentative dans l'ensemble a semester
été la suivante:
def team_constraint(self, *semester):
students = defaultdict(list)
# get back each teams based on the format [# Semester [ #Session [# Practice/Team ...
teams = [list(semester[i:i+4]) for i in range(0, len(semester), 4)]
# Update Students dict with all mate they work with
for team in teams:
for student in team:
students[student] += [s for s in team if s != student]
# Compute for each student if they meet someone more than once
dupli = []
for student, mate in students.items():
dupli.append(len(mate) - len(set(mate)))
# Loosly constraint, if a student meet somone 0 or one time it's find
if max(dupli) >= 2:
print("Mate encounter more than one time", dupli, min(dupli) ,max(dupli))
return False
pprint(students)
return True
Des questions :
- Est-il possible de faire ce que je veux pour les conditions de l'équipe? Ce que je veux dire, c'est que je n'ai aucune idée s'il est possible d'affecter 12 camarades à chaque élève et que chacun d'eux ne rencontre le même compagnon qu'une seule fois.
- Pour la contrainte d'équipe, ai-je manqué un algorithme plus performant?
- Des pistons que je peux suivre?
la source
(4, 4)
plutôt(4, 6)
que les autres?Réponses:
On répondrait à la question principale par quelque chose comme ...
Ajouté Modifier
J'ai revu votre problème hier - (certes pas longtemps, car j'ai beaucoup de travail en ce moment), et ...
Tout d'abord, je vois que votre entité «équipe» est à peu près ce que j'ai appelé une entité «action» et, rétrospectivement, je pense que «équipe» (ou «groupe») était un meilleur mot pour cela.
Si vous trouvez toujours les contraintes difficiles, je vous suggère de les décomposer et de les travailler individuellement - en particulier les contraintes équipe / personne / session, suivies des contraintes rôle / tâche.
/ Modification ajoutée
J'ai eu un problème similaire récemment et je me suis finalement tourné vers les outils OR. https://developers.google.com/optimization/cp/cp_solver
En particulier, jetez un œil au problème de planification des infirmières: https://developers.google.com/optimization/scheduling/employee_scheduling#nurse_scheduling
Quoi qu'il en soit, le problème n'est pas trop complexe, alors peut-être que l'utilisation d'un solveur serait exagéré pour vous.
De même, pour ce type de problème, il peut être préférable d'utiliser un dict à clé double pour contenir vos variables, plutôt que des listes imbriquées:
{Équipe, session, personne: BoolVar}
La raison principale est que vous pouvez ensuite appliquer des contraintes via des filtres, ce qui est beaucoup plus facile que d'avoir à manipuler des listes imbriquées, par exemple, pour appliquer une contrainte à travers des personnes / équipes, vous pouvez le faire (où personne est l'index 2 et l'équipe est l'index 0):
la source
p for p in all_people
?Juste une idée d'algorithme de permutation, pour chaque itération pourrait être concentrée sur un de chaque étudiant ou dans une de chaque session:
Ici, l'étudiant 2 prend la place de l'étudiant 1 dans la session 1 et continue comme ça
Continuer avec l'élève 1 S3 R 1234 St 10,9,1,8
À la fin, vous supprimez les interactions pour l'étudiant 1, comme sur les permutations pour la prochaine itération que vous supprimez en cours.
C'est comme un cube rubiks.
Si vous arrivez à coder ceci ou connaissez du code avec cet algo, faites le moi savoir.
Peut-être avec les permutations d' itertools
Les sessions étant> que des pratiques, je crois que ce n'est pas pertinent son nombre. Juste un peu de piscine pour en prendre plus quand vous manquez ou plus de place pour la rotation. Peut-être pourrait simplifier le problème en visant d'abord 4 séances = pratiques?
la source