This commit is contained in:
2022-11-08 21:19:51 +01:00
commit 4c456eafc3
160 changed files with 21472 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
"""
Ce module contient les Utilitaires de matching
"""
# import des pré requis
import time
import pandas as pd
from matching.games import HospitalResident
from .models import Notation, Poste, PreferencesListe, StatutPamChoices, AvisPosteChoices as AvisPoste
from .utils.logging import get_logger
logger = get_logger(__name__)
# Fonction de preprocessing
def preprocess_matching(pam_id,sv_id,df_pref):
"""
Retourne les liste de souhait des militaires et des postes
:type sv_id: char
:param sv_id: id du sous vivier étudié
:return: - **gs_proposants** (*liste*): liste des proposants
- **gs_disposants** (*liste*): liste des disposants
- **gs_capacite** (*liste*): liste des capacités pour chaque disposants
"""
logger.debug('preprocessing matching %s', sv_id)
statut_adm = [StatutPamChoices.A_MUTER,StatutPamChoices.A_ETUDIER]
statut_poste =[AvisPoste.P1,AvisPoste.P2,AvisPoste.P3,AvisPoste.P4]
# liste_preference = PreferencesListe.objects.filter(pam_id=pam_id,administre_pam__administre__sous_vivier_id=sv_id).values()
notation = Notation.objects.filter(pam_id=pam_id,
administre_pam__administre__sous_vivier_id=sv_id,
administre_pam__a_statut_pam_annee__in=statut_adm,
administre_pam__decision__de_decision__isnull=True,
poste_pam__poste__sous_viviers=sv_id,
poste_pam__decisions__de_decision__isnull=True,
poste_pam__p_avis_pam__in=statut_poste).values()
liste_preference_df = df_pref
notation_df = pd.DataFrame.from_records(notation)
liste_admin_lp = liste_preference_df.drop_duplicates(subset=['administre_id'])
gs_proposants = {}
gs_disposants = {}
gs_capacite = {}
l2 = []
if not liste_preference_df.empty:
for admin in liste_admin_lp['administre_id']:
l = []
new_lp_df = liste_preference_df.loc[liste_preference_df['administre_id'] == admin].drop_duplicates(subset=['poste_id'])
new_lp_df = new_lp_df.drop_duplicates(subset=['lp_rang_poste'])
new_lp_df = new_lp_df.sort_values(
by=['lp_rang_poste']).reset_index()
for i in range(len(new_lp_df)):
l.append(new_lp_df.at[i, 'poste_id'])
l2.append(new_lp_df.at[i, 'poste_id'])
gs_proposants[admin] = l
l2 = list(set(l2))
notation_df = notation_df[notation_df.administre_id.isin(liste_admin_lp['administre_id'])]
for poste in l2:
l1 = []
new_no_df = notation_df.loc[notation_df['poste_id'] == poste].sort_values(by=['no_score_administre'],
ascending=False).reset_index()
for i in range(len(new_no_df)):
if poste in gs_proposants[new_no_df.at[i, 'administre_id']]:
l1.append(new_no_df.at[i, 'administre_id'])
gs_disposants[poste] = l1
gs_capacite[poste] = 1
logger.debug("Administre proposants : %s", gs_proposants)
logger.debug("Poste disposants : %s", gs_disposants)
logger.debug('end preprocessing matching func')
return gs_proposants, gs_disposants, gs_capacite
# Fonction de preprocessing
def preprocess_matchingSelectif(sv_id, pam_id,l_a_id,l_p_id, df_pref):
"""
Retourne les liste de souhait des militaires et des postes
:type sv_id: char
:param sv_id: id du sous vivier étudié
:return: - **gs_proposants** (*liste*): liste des proposants
- **gs_disposants** (*liste*): liste des disposants
- **gs_capacite** (*liste*): liste des capacités pour chaque disposants
"""
logger.debug('preprocessing matching %s', sv_id)
statut_adm = [StatutPamChoices.A_MUTER,StatutPamChoices.A_ETUDIER]
statut_poste =[AvisPoste.P1,AvisPoste.P2,AvisPoste.P3,AvisPoste.P4]
notation = Notation.objects.filter(pam_id=pam_id,
administre_pam__administre__sous_vivier_id=sv_id,
administre_pam__a_statut_pam_annee__in=statut_adm,
administre_pam__administre_id__in=l_a_id,
administre_pam__decision__de_decision__isnull=True,
poste_pam__poste__sous_viviers=sv_id,
poste_pam__decisions__de_decision__isnull=True,
poste_pam__p_avis_pam__in=statut_poste).values()
liste_preference_df = df_pref
notation_df = pd.DataFrame.from_records(notation)
liste_admin_lp = liste_preference_df.drop_duplicates(subset=['administre_id'])
gs_proposants = {}
gs_disposants = {}
gs_capacite = {}
l2 = []
if not liste_preference_df.empty:
for admin in liste_admin_lp['administre_id']:
l = []
new_lp_df = liste_preference_df.loc[liste_preference_df['administre_id'] == admin].drop_duplicates(subset=['poste_id'])
new_lp_df = new_lp_df.drop_duplicates(subset=['lp_rang_poste'])
new_lp_df = new_lp_df.sort_values(
by=['lp_rang_poste']).reset_index()
for i in range(len(new_lp_df)):
l.append(new_lp_df.at[i, 'poste_id'])
l2.append(new_lp_df.at[i, 'poste_id'])
gs_proposants[admin] = l
l2 = list(set(l2))
notation_df = notation_df[notation_df.administre_id.isin(liste_admin_lp['administre_id'])]
for poste in l2:
l1 = []
new_no_df = notation_df.loc[notation_df['poste_id'] == poste].sort_values(by=['no_score_administre'],
ascending=False).reset_index()
for i in range(len(new_no_df)):
if poste in gs_proposants[new_no_df.at[i, 'administre_id']]:
l1.append(new_no_df.at[i, 'administre_id'])
gs_disposants[poste] = l1
gs_capacite[poste] = 1
logger.debug("Administre proposants : %s", gs_proposants)
logger.debug("Poste disposants : %s", gs_disposants)
logger.debug('end preprocessing matching func')
return gs_proposants, gs_disposants, gs_capacite
# Fonction de matching
def matching_parfait(gs_proposants, gs_disposants, gs_capacite):
"""
Retourne le dictionnaire python presentant le resultats du matching
:type gs_proposants: liste
:param gs_proposants: liste des proposants
:type gs_disposants: liste
:param gs_disposants: liste des disposants
:type gs_capacite: liste
:param gs_capacite: liste des capacités pour chaque disposants
:return: - **matching** (*dictionnaire*): dictionnaire python presentant le resultats du matching
"""
logger.debug('start matching parfait')
# Traitement des entrées
game = HospitalResident.create_from_dictionaries(
gs_proposants, gs_disposants, gs_capacite
)
# Creation du jeu
matching = game.solve(optimal='hospital')
# Test de validation et de stabilité
logger.debug('Validity Check : %s', game.check_validity())
assert game.check_validity()
logger.debug('Stability Check : %s', game.check_stability())
assert game.check_stability()
# Creation des listes d'affectés et de non afféctes
matched_residents = []
for _, residents in matching.items():
for resident in residents:
matched_residents.append(resident.name)
unmatched_residents = set(gs_proposants.keys()) - set(matched_residents)
# KPI matching
logger.debug("Nb demandeurs : %s", len(gs_proposants))
logger.debug("Poste demandeurs : %s", gs_proposants)
logger.debug("Nb affectés : %s", len(matched_residents))
logger.debug("Administres affectés : %s", matched_residents)
logger.debug("Nb non affecte : %s", len(unmatched_residents))
logger.debug("Administres non affecte : %s", unmatched_residents)
logger.debug('end matching parfait')
return (matching)