init
This commit is contained in:
190
backend-django/backend/utils_matching.py
Normal file
190
backend-django/backend/utils_matching.py
Normal 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)
|
||||
Reference in New Issue
Block a user