[PYTHON] Décidons le gagnant du bingo

problème

Je ferai du bingo à la fête de fin d'année de l'entreprise. On vous a demandé de développer un système de bingo. Cependant, il existe les exigences suivantes (fiction).

―― "7 prix" (→ 7 gagnants) ―― "Veuillez garder le ratio de gagnants entre hommes et femmes aussi constant que possible." ―― "Veuillez garder le ratio de gagnants constant dans chaque département autant que possible." ―― "Définissez la probabilité de gagner (poids) des jeunes, des vétérans et des officiers sur 1, 2, 3"

(Référence: Histoire similaire)

Façon de penser

Avec l'optimisation des combinaisons, vous pouvez trouver des combinaisons qui prennent en compte diverses conditions. Les gagnants sont sélectionnés et classés par ordre en fonction de la probabilité de gagner. Selon l'ordre, le $ i $ e score est de 2 $ ^ {1-i} $. En maximisant la somme des scores, nous sélectionnerons les gagnants en fonction de la probabilité de gagner autant que possible. Le ratio hommes / femmes et le ratio de départements sont soustraits de la fonction objectif en pénalisant le montant qui s'écarte du ratio.

Résoudre avec Python

Chargez les informations du participant dans pandas.DataFrame (si le code ne peut pas être exécuté, téléchargez le CSV à partir de l'URL et chargez-le).

import numpy as np, pandas as pd, urllib
from pulp import lpDot, lpSum
from ortoolpy import model_max, addbinvars, addvars, addvals

url = 'https://www.dropbox.com/s/refo0vfj5wbmv2h/bingo.csv?dl=1'
with urllib.request.urlopen(url) as fp:
    df = pd.read_csv(fp)

Création de partitions et de variables

Chaque ligne de DataFrame (df) est un participant. La probabilité de gagner (colonne Taux) est utilisée comme un ratio pour gagner dans l'ordre avec numpy.random.choice. Calculez le score avec cet ordre comme index et insérez-le dans la colonne Score. L'optimisation maximise la somme des scores.

Ajoutez une colonne de variables indiquant si vous avez gagné ou non, «Var». De plus, «pena1» est une sanction qui s'écarte du rapport hommes / femmes. Soit «pena2» le montant de la pénalité qui s'écarte du ratio d'affiliation.

nn = len(df)  #Nombre de personnes
rnd = np.random.choice(df.index, nn, False, df.Rate / df.Rate.sum())
df['Score'] = pd.Series(2.0**-np.arange(nn), index=rnd)  #But
addbinvars(df)  #Variable ajoutée (gagnante ou non) en tant que colonne Var
pena1, pena2 = addvars(2)  #Deux pénalités pour dérogation au ratio
print(df)
Name IsMale Div Rate Score Var
0 Hidehito Asakura True Département des affaires générales 2 0.000488 v000001
1 Ryoharu Miyakawa True Service de la comptabilité 1 0.001953 v000002
2 Kenji Furuhashi True Département des affaires générales 2 0.000977 v000003
3 Fumi Motomura False Département des affaires générales 3 0.000015 v000004
4 Keiji Otsubo True Service de la comptabilité 1 0.000002 v000005
5 Kazutaka Hatakeyama True Département des affaires générales 2 0.000031 v000006
6 Wakana Takeuchi False Service de la comptabilité 2 0.000008 v000007
7 Kana Yoda False Département des Ressources Humaines 2 0.015625 v000008
8 Keisuke Furuta True Département des Ressources Humaines 3 0.125000 v000009
9 Kei Ishikawa True Département des Ressources Humaines 1 0.000061 v000010
10 Eriko Tominaga False Département des Ressources Humaines 2 1.000000 v000011
11 Sato Tobita False Département des affaires générales 1 0.003906 v000012
12 Seito Kamiyama True Département des Ressources Humaines 2 0.250000 v000013
13 Ryuichiro Tabata True Département des affaires générales 3 0.500000 v000014
14 Rie Kamei False Service de la comptabilité 1 0.000004 v000015
15 Atsuka Sone False Département des affaires générales 1 0.000244 v000016
16 Kiyoshiro Kasuga True Service de la comptabilité 2 0.007812 v000017
17 Akisa Nakai False Service de la comptabilité 3 0.062500 v000018
18 Yukio Kinjo False Département des Ressources Humaines 2 0.031250 v000019
19 Yoshikatsu Kakinuma True Département des affaires générales 1 0.000122 v000020

Vérifiez le nombre de personnes par sexe et service.

print(df.groupby('IsMale').Div.value_counts())
IsMale  Div
Faux département des ressources humaines 3
Département Comptabilité 3
Département des affaires générales 3
Véritable département des affaires générales 5
Département des ressources humaines 3
Département Comptabilité 3
Name: Div, dtype: int64

Créez un modèle mathématique et résolvez-le

--Fonction d'objet: Somme des scores --Nombre de personnes x (Montant de l'écart par rapport au rapport entre les sexes + Montant de l'écart par rapport au rapport du département) --Restrictions --Le nombre de gagnants est de 7 --Rapport constant par sexe --Rapport constant par département

ns = 7  #Nombre de gagnants

m = model_max()  #Modèle mathématique
m += lpDot(df.Score, df.Var) - nn * (pena1 + pena2)  #Fonction objective
m += lpSum(df.Var) == ns  #Nombre de gagnants
for _, gr in df.groupby('IsMale'):  #Gardez le ratio par sexe constant
    m += lpSum(gr.Var) <= ns * len(gr) / nn + pena1
for _, gr in df.groupby('Div'):  #Gardez le ratio par département constant
    m += lpSum(gr.Var) <= ns * len(gr) / nn + pena2
m.solve()  #Solution
addvals(df)  #Ajouter le résultat en tant que colonne Val
print(df[df.Val > 0])  #Gagnant
Name IsMale Div Rate Score Var Val
10 Eriko Tominaga False Département des Ressources Humaines 2 1.000000 v000011 1.0
11 Sato Tobita False Département des affaires générales 1 0.003906 v000012 1.0
12 Seito Kamiyama True Département des Ressources Humaines 2 0.250000 v000013 1.0
13 Ryuichiro Tabata True Département des affaires générales 3 0.500000 v000014 1.0
16 Kiyoshiro Kasuga True Service de la comptabilité 2 0.007812 v000017 1.0
17 Akisa Nakai False Service de la comptabilité 3 0.062500 v000018 1.0
19 Yoshikatsu Kakinuma True Département des affaires générales 1 0.000122 v000020 1.0

Les gagnants ont été choisis. Regardons le nombre de personnes par sexe et département.

print(df[df.Val > 0].groupby('IsMale').Div.value_counts())
IsMale  Div
Faux département des ressources humaines 1
Département Comptabilité 1
Département des affaires générales 1
Véritable département des affaires générales 2
Département des ressources humaines 1
Département Comptabilité 1
Name: Div, dtype: int64

Cela semble bon.

Résumé

――Une combinaison qui satisfait diverses conditions est obtenue par une méthode appelée optimisation de combinaison.

(Personnellement, j'espère qu'il n'y a pas de demande pour cet article)

c'est tout

Recommended Posts

Décidons le gagnant du bingo
Décidons la position du service d'incendie par optimisation combinée
Examinons le mécanisme de la chinchirorine de Kaiji
Décidons le cours de date par optimisation de combinaison
Le début de cif2cell
Le sens de soi
Utilisons l'API de la fenêtre générale des statistiques gouvernementales (e-Stat)
Supprimons maintenant l'ambiguïté du trait d'union (-) de la commande su! !!
Décomposons les bases du code Python de TensorFlow
le zen de Python
L'histoire de sys.path.append ()
Utilisons la version Python du module API Confluence.
Utilisons les données ouvertes de "Mamebus" en Python
Testons l'hypothèse d'effondrement médical du nouveau virus corona
[Ev3dev] Comprenons le mécanisme de contrôle LCD (écran)
Analysons les émotions de Tweet en utilisant Chainer (1er)
La vengeance des types: la vengeance des types
[Python] Changeons l'URL du site administrateur de Django
Traversons le mur du système de coordonnées gauche et du système de coordonnées droitier.
Visualisons le volume des transactions des actions TSE - Exemple Jpxlab
Pepper décide du gagnant en mesurant l'ampleur des applaudissements du public
Utilisons les données ferroviaires des informations numériques foncières nationales
Faisons l'analyse des données de naufrage du Titanic comme ça
Exécutons la commande à temps avec le bot discord
Prédisons le timing de Barus et apprécions le film lentement
Devinons l'état de développement de la ville à partir de l'image satellite.
Visualisons le nombre de personnes infectées par le virus corona avec matplotlib
Utilisons rapidement l'expression distribuée des mots avec fastText!
Aligner la version de chromedriver_binary
Grattage du résultat de "Schedule-kun"
10. Compter le nombre de lignes
L'histoire de la construction de Zabbix 4.4
Vers la retraite de Python2
Cherchons à partir de la ligne
Comparez les polices de jupyter-themes
Obtenez le nombre de chiffres
Faisons tourner l'air gacha
Expliquez le code de Tensorflow_in_ROS
Réutiliser les résultats du clustering
GoPiGo3 du vieil homme
Calculez le nombre de changements
Changer le thème de Jupyter
La popularité des langages de programmation
Changer le style de matplotlib
À propos des composants de Luigi
Filtrer la sortie de tracemalloc
Simulation du contenu du portefeuille
Le pouvoir des pandas: Python
[Note] Essayons de prédire la quantité d'électricité utilisée! (Partie 1)
Jetons un coup d'œil à la carte des fonctionnalités de YOLO v3
Mesurez la couverture de test du code python poussé sur GitHub.
[Python] Réduisons le nombre d'éléments dans le résultat dans le fonctionnement de l'ensemble
Résumons le degré de couplage entre les modules avec du code Python
[Word2vec] Visualisons le résultat du traitement en langage naturel des avis des entreprises