Commit aa5295a3 authored by Pierre-antoine Comby's avatar Pierre-antoine Comby

le dépot est propre

parents
__pycache__/
*.csv
""" This script contains both the standard and extended Gale-Shapley algorithms
for solving matching games.
A matching game is defined by two sets called suitors and reviewers. Each suitor
(and reviewer) has associated with it an ordered preference of the elements of
the corresponding set. A solution to a matching game is any mapping between the
set of suitors and reviewers.
"""
from collections import Counter
from copy import deepcopy
import numpy as np
def galeshapley(suitor_pref_dict, reviewer_pref_dict):
""" The Gale-Shapley algorithm. This is known to provide a unique, stable
suitor-optimal matching. The algorithm is as follows:
(1) Assign all suitors and reviewers to be unmatched.
(2) Take any unmatched suitor, s, and their most preferred reviewer, r.
- If r is unmatched, match s to r.
- Else, if r is matched, consider their current partner, r_partner.
- If r prefers s to r_partner, unmatch r_partner from r and
match s to r.
- Else, leave s unmatched and remove r from their preference
list.
(3) Go to (2) until all suitors are matched, then end.
Parameters
----------
suitor_pref_dict : dict
A dictionary with suitors as keys and their respective preference lists
as values
review_pref_dict : dict
A dictionary with reviewers as keys and their respective preference
lists as values
Returns
-------
matching : dict
The suitor-optimal (stable) matching with suitors as keys and the
reviewer they are matched with as values
"""
suitors = [s for s in suitor_pref_dict]
matching = {s: None for s in suitors}
while suitors != []:
s = suitors.pop(0)
r = suitor_pref_dict[s][0]
if r not in matching.values():
matching[s] = r
else:
for suitr, revwr in matching.items():
if revwr == r:
r_partner = suitr
if reviewer_pref_dict[r].index(s) < reviewer_pref_dict[r].index(
r_partner
):
matching[r_partner] = None
matching[s] = r
suitors.append(r_partner)
else:
suitor_pref_dict[s].remove(r)
suitors.append(s)
return matching
def get_free_residents(resident_prefs, matching):
""" Return a list of all residents who are currently unmatched but have a
non-empty preference list. """
return [
resident
for resident in resident_prefs
if resident_prefs[resident]
and not any([resident in match for match in matching.values()])
]
def get_worst_idx(hospital, hospital_prefs, matching):
""" Find the index of the worst resident currently assigned to `hospital`
according to their preferences. """
return max(
[
hospital_prefs[hospital].index(resident)
for resident in hospital_prefs[hospital]
if resident in matching[hospital]
]
)
def resident_hospital(resident_prefs, hospital_prefs, capacities):
""" Provide a stable, resident-optimal matching for the given instance of
HR using the algorithm set out in [Gale, Shapley 1962]. """
matching = {hospital: [] for hospital in hospital_prefs}
free_residents = get_free_residents(resident_prefs, matching)
while free_residents:
resident = free_residents[0]
hospital = resident_prefs[resident][0]
i = 0
while capacities[hospital] <= 0:
i += 1
hospital = resident_prefs[resident][i]
<<<<<<< HEAD
=======
>>>>>>> 7158617afbb760d3a35b62a2705688d11b9d0b1b
matching[hospital].append(resident)
if len(matching[hospital]) > capacities[hospital]:
worst = get_worst_idx(hospital, hospital_prefs, matching)
resident = hospital_prefs[hospital][worst]
matching[hospital].remove(resident)
if len(matching[hospital]) == capacities[hospital]:
worst = get_worst_idx(hospital, hospital_prefs, matching)
successors = hospital_prefs[hospital][worst + 1 :]
if successors:
for resident in successors:
hospital_prefs[hospital].remove(resident)
if hospital in resident_prefs[resident]:
resident_prefs[resident].remove(hospital)
free_residents = get_free_residents(resident_prefs, matching)
for hospital, matches in matching.items():
sorted_matches = sorted(matches, key=hospital_prefs[hospital].index)
matching[hospital] = sorted_matches
return matching
def hrt_super_res(resident_prefs, hospital_prefs, capacities):
""" Determine whether a super-stable, resident-optimal matching exists for
the given instance of HR. If so, return the matching. """
# ==================================
# Needs adjusting for ties in prefs.
# ==================================
matching = {h: [] for h in hospital_prefs.keys()}
fulls = {h: False for h in hospital_prefs.keys()}
free_residents = [r for r in resident_prefs.keys()]
while [r for r in free_residents if resident_prefs[r]]:
r = free_residents.pop(0)
r_prefs = resident_prefs[r]
h_best = r_prefs[0]
matching[h_best] += [r]
if len(matching[h_best]) > capacities[h_best]:
r_worst = hospital_prefs[h_best][-1]
if r_worst in matching[h_best]:
matching[h_best].remove(r_worst)
resident_prefs[r_worst].remove(h_best)
hospital_prefs[h_best].remove(r_worst)
if len(matching[h_best]) == capacities[h_best]:
fulls[h_best] = True
worst_idx = np.max(
[
hospital_prefs[h_best].index(resident)
for resident in hospital_prefs[h_best]
if resident in matching[h_best]
]
)
successors = hospital_prefs[h_best][worst_idx + 1 :]
if successors:
for resident in successors:
hospital_prefs[h_best].remove(resident)
resident_prefs[resident].remove(h_best)
resident_match_counts = Counter([tuple(res) for res in matching.values()])
if np.any(
[count > 1 for count in resident_match_counts.values()]
) or np.any(fulls.values()):
raise ValueError("No super-stable matching exists.")
return matching
#! /usr/bin/env python3
BUS = ['Nausi[car] de la vallee du [van]',
'Au [bus]cher',
'La grosse [caisse]',
'Ha[van]a Club',
'l houm[bus]',
'[Van]ted',
'Pernod-Ri[Car]d']
NB_BUS=8
class Bus(object):
"""Un bus contient des équipes , remplis par des 1A en fonction de leur réponse à un questionnaire
"""
def __init__(self, nom, places, places_2a,reponse_criteres,size_equipe):
self.nom = nom # nom du bus
self.criteres = reponse_criteres # critère et pondération
self.note = dict() # note de tous les 1A par rapport à ce bus.
self.rank_unA = []
self.passengers = []
self.old_passengers = []
self.size_team = [int(s) for s in size_equipe]
self.teams = []
self.places = places
self.places_2a = places_2a
self.places_1a = places-places_2a
def __repr__(self):
ret = self.nom
return"Bus_"+ret
def __str__(self):
return "Bus {}".format(self.nom)
def __str__(self):
return "Bus {}".format(self.nom)
def gen_note(self, list_unA):
for unA in list_unA:
score_unA = unA.scores_bus[self]
rank_unA = unA.rank_bus.index(self)
if rank_unA == NB_BUS-1:
note_bus = score_unA/rank_unA
else:
#note_bus = (score_unA-unA.scores_bus[unA.rank_bus[rank_unA+1]] + 2)/(rank_unA+1)
p = NB_BUS - rank_unA
nextu = unA.scores_bus[unA.rank_bus[rank_unA+1]]
tmp = ((NB_BUS - rank_unA) * score_unA - (NB_BUS - rank_unA - 1) * nextu) / (rank_unA + 1)
note_bus = tmp
#note_bus = (score_unA**p - next**(p - 1))
# note_bus = (score_unA-unA.scores_bus[unA.rank_bus[rank_unA+1]])
self.note[unA] = note_bus
def gen_rank(self):
self.rank_unA = list(self.note.items())
self.rank_unA = sorted(self.rank_unA,key=lambda x:x[1],reverse = True)
self.rank_unA = [r[0] for r in self.rank_unA]
def partial_rank(self, students):
return [student for student in self.rank_unA if student in students]
def make_teams(self):
print(self.nom)
n_chef_tot = sum(self.size_team)
n_equipe = len(self.size_team)
N = len(self.passengers)
size_goal = [0]*len(self.size_team)
for i in range(len(self.size_team)):
size_goal[i] = int(self.size_team[i]*N/n_chef_tot)+1
i = 0
places_equipe=sum(size_goal)
girls = [p for p in self.passengers
if p.infos["genre"] == 'F' or p.infos["genre"] == 'N']
not_girls = [p for p in self.passengers
if p.infos["genre"] == 'M']
#
# for e in size_goal:
# equipe = []
# for k in range(int(len(girls)*e/places_equipe)):
# if girls:
# equipe.append(girls.pop())
# for k in range(int(len(not_girls)*e/places_equipe)):
# if not_girls:
# equipe.append(not_girls.pop())
# print(len(equipe))
# self.teams.append(equipe)
i=0
self.teams=[[None]*s for s in size_goal]
while girls :
if None in self.teams[i]:
self.teams[i].append(girls.pop())
self.teams[i].remove(None)
i +=1; i %= n_equipe;
for i in range(len(self.size_team)):
if len(self.teams[i])-self.teams[i].count(None) == 1:
#Si une fille est seule on l'enlève.
g_alone=self.teams[i].pop()
self.teams[i].append(None)
next_ind = (i+1)%n_equipe
self.teams[next_ind].remove(None)
self.teams[next_ind].append(g_alone)
remain =True
while not_girls and remain:
if None in self.teams[i]:
self.teams[i].append(not_girls.pop())
self.teams[i].remove(None)
i +=1; i %= n_equipe;
#cleaned unused places
for l in self.teams:
while None in l:
l.remove(None)
#affichage
for k in range(len(self.size_team)):
print(self.size_team[k],size_goal[k],len(self.teams[k]),self.teams[k])
print(len(self.passengers),sum(size_goal))
def partial_rank(self, students):
return [student for student in self.rank_unA if student in students]
{
"aspique":[978,1004,1112,1042,1092,1083,1145,963,975,1059,934,931,1082,1046,1084,961,1097,1195,944,1106,952,942,1071,1134],
"chytem":[1002],
"fanfare":[947,997,929,930, 1066],
"hooligens":[1050,1006,962,1013],
"med":[951,956],
"saphire":[1118,1111],
"satelist":[1016,1114],
"vieux":[974, 1066,943]
}
This diff is collapsed.
#!/usr/bin/env python3
# -*- coding:utf-8 -*
"""Pour récupérer des infos à partir du wiki."""
import time
import re
#import urllib.request
import pprint
#: URL de la page wiki des bus
URL = "https://wiki.crans.org/OrganisationWei{}/Bus?action=raw".format(
time.localtime()[0])
FILE = "rawpage"
def get_raw():
"""Récupère le contenu de la page."""
return open(FILE).read()
# page = urllib.request.urlopen(URL)
# text = page.read().decode("utf-8")
return text
def parse_names(raw):
"""Récupère les tableaux de Bus (= un tableau après un titre commençant par '== Bus')."""
names = []
l = re.findall("== (?:Bi)?Bus.*==[^|]*\n((?:\|\|.*\|\|\n)+)", raw)
for table in l:
obj = re.search("Nom de l'équipe[^|]*\|\|", table)
after = table[obj.end():]
end = after.index("\n")
after = after[:end]
teams = re.findall("([^|]+)\|\|", after)
teams = [t.strip() for t in teams]
names.append(teams)
return names
def get_team_names():
raw = get_raw()
teams = parse_names(raw)
return teams
if __name__ == "__main__":
for t in get_team_names():
print(t)
This diff is collapsed.
#!/usr/bin/env python3
INFOS = [
"idwei",
"nom",
"prenom",
"genre",
"dept",
"tel",
"urgence_nom",
"urgence_tel",
"mail",
"infos"
]
INFOS_2A =INFOS + [
"idbde",
"bus",
"role"
]
CRITERES = {
"q_soirees",
"q_alcools",
"q_encadrement",
"q_groupe",
"q_sociable",
"q_chants",
"q_boire",
"q_assos",
"q_activites",
"q_personnes",
"q_suiveur",
"q_conquetes"
}
class People(object):
def __init__(self, infos):
self.infos = infos
def __repr__(self):
return repr("P_"+self.infos["nom"])
def __str__(self):
return "{} {}".format(self.infos["nom"].upper(), self.infos["prenom"])
class UnA(People):
"""un 1A est une gentille personne qui veux faire plein de rencontre dans le bon bus."""
def __init__(self, infos, reponse_criteres):
People.__init__(self,infos)
self.criteres = reponse_criteres
self.scores_bus = dict()
self.rank_bus = []
def __repr__(self):
return repr("unA_"+self.infos["nom"])
def __str__(self):
return "{} {}".format(self.infos["nom"].upper(), self.infos["prenom"])
def score_question(self,ans1a, ansbus):
"""
Calcule le score pour une question,
Connaissance la réponse du 1A, celle du bus, et l'importance.
"""
MAX = 3
MIN = -MAX
delta = abs(ans1a*2 - ansbus) # unA /5 , bus /10
s = (MAX - MIN) * (- delta / 4.) + MAX
return s
def score_questions(self, crit_bus):
"""
Calcule le score total pour 1 bus.
"""
s = 0
for crit in self.criteres:
s += self.score_question(self.criteres[crit],crit_bus[crit])
return s
def gen_score(self, list_bus):
for bus in list_bus:
self.scores_bus[bus] = self.score_questions(bus.criteres)
def gen_rank(self):
#self.rank_bus = list(self.scores_bus.keys())
#self.rank_bus = sorted(self.scores_bus,key=self.scores_bus.get)
self.rank_bus = list(self.scores_bus.items())
self.rank_bus = sorted(self.rank_bus,key=lambda x:x[1],reverse = True)
self.rank_bus = [r[0] for r in self.rank_bus]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment