Ich werde auf der Jahresendparty des Unternehmens Bingo spielen. Sie wurden gebeten, ein System für Bingo zu entwickeln. Es gibt jedoch die folgenden Anforderungen (Fiktion).
(Referenz: Ähnliche Geschichte)
Mit der Kombinationsoptimierung können Sie Kombinationen finden, die verschiedene Bedingungen berücksichtigen. Die Gewinner werden entsprechend der Gewinnwahrscheinlichkeit ausgewählt und sortiert. Entsprechend der Reihenfolge beträgt die $ i $ -te Punktzahl $ 2 ^ {1-i} $. Indem wir die Summe der Punkte maximieren, werden wir die Gewinner so weit wie möglich nach der Gewinnwahrscheinlichkeit auswählen. Das Verhältnis von Männern und Frauen und das Verhältnis der Abteilungen werden von der Zielfunktion abgezogen, indem der vom Verhältnis abweichende Betrag bestraft wird.
Laden Sie die Teilnehmerinformationen in pandas.DataFrame (wenn der Code nicht ausgeführt werden kann, laden Sie die CSV von der URL herunter und laden Sie sie).
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)
Jede Zeile von DataFrame (df
) ist ein Teilnehmer.
Die Gewinnwahrscheinlichkeit (Spalte "Rate") wird als Verhältnis zum Gewinnen in der Reihenfolge "numpy.random.choice" verwendet. Berechnen Sie die Punktzahl mit dieser Reihenfolge als Index und fügen Sie sie in die Spalte "Punktzahl" ein.
Die Optimierung maximiert die Summe der Ergebnisse.
Fügen Sie eine Spalte mit Variablen hinzu, die angeben, ob Sie gewonnen haben oder nicht, "Var". Außerdem ist "pena1" eine Strafe, die vom Verhältnis von Männern und Frauen abweicht. Sei "pena2" die Höhe der Strafe, die von der Zugehörigkeitsquote abweicht.
nn = len(df) #Anzahl der Personen
rnd = np.random.choice(df.index, nn, False, df.Rate / df.Rate.sum())
df['Score'] = pd.Series(2.0**-np.arange(nn), index=rnd) #Ergebnis
addbinvars(df) #Variable (ob gewinnend oder nicht) als Var-Spalte hinzugefügt
pena1, pena2 = addvars(2) #Zwei Strafen für die Abweichung vom Verhältnis
print(df)
Name | IsMale | Div | Rate | Score | Var | |
---|---|---|---|---|---|---|
0 | Hidehito Asakura | True | Abteilung Allgemeine Angelegenheiten | 2 | 0.000488 | v000001 |
1 | Ryoharu Miyakawa | True | Buchhaltung | 1 | 0.001953 | v000002 |
2 | Kenji Furuhashi | True | Abteilung Allgemeine Angelegenheiten | 2 | 0.000977 | v000003 |
3 | Fumi Motomura | False | Abteilung Allgemeine Angelegenheiten | 3 | 0.000015 | v000004 |
4 | Keiji Otsubo | True | Buchhaltung | 1 | 0.000002 | v000005 |
5 | Kazutaka Hatakeyama | True | Abteilung Allgemeine Angelegenheiten | 2 | 0.000031 | v000006 |
6 | Wakana Takeuchi | False | Buchhaltung | 2 | 0.000008 | v000007 |
7 | Kana Yoda | False | Personalabteilung | 2 | 0.015625 | v000008 |
8 | Keisuke Furuta | True | Personalabteilung | 3 | 0.125000 | v000009 |
9 | Kei Ishikawa | True | Personalabteilung | 1 | 0.000061 | v000010 |
10 | Eriko Tominaga | False | Personalabteilung | 2 | 1.000000 | v000011 |
11 | Sato Tobita | False | Abteilung Allgemeine Angelegenheiten | 1 | 0.003906 | v000012 |
12 | Seito Kamiyama | True | Personalabteilung | 2 | 0.250000 | v000013 |
13 | Ryuichiro Tabata | True | Abteilung Allgemeine Angelegenheiten | 3 | 0.500000 | v000014 |
14 | Rie Kamei | False | Buchhaltung | 1 | 0.000004 | v000015 |
15 | Atsuka Sone | False | Abteilung Allgemeine Angelegenheiten | 1 | 0.000244 | v000016 |
16 | Kiyoshiro Kasuga | True | Buchhaltung | 2 | 0.007812 | v000017 |
17 | Akisa Nakai | False | Buchhaltung | 3 | 0.062500 | v000018 |
18 | Yukio Kinjo | False | Personalabteilung | 2 | 0.031250 | v000019 |
19 | Yoshikatsu Kakinuma | True | Abteilung Allgemeine Angelegenheiten | 1 | 0.000122 | v000020 |
Überprüfen Sie die Anzahl der Personen nach Geschlecht und Abteilung.
print(df.groupby('IsMale').Div.value_counts())
IsMale Div
Falsche Personalabteilung 3
Buchhaltungsabteilung 3
Abteilung für allgemeine Angelegenheiten 3
Abteilung für wahre allgemeine Angelegenheiten 5
Personalabteilung 3
Buchhaltungsabteilung 3
Name: Div, dtype: int64
ns = 7 #Anzahl der Gewinner
m = model_max() #Mathematisches Modell
m += lpDot(df.Score, df.Var) - nn * (pena1 + pena2) #Zielfunktion
m += lpSum(df.Var) == ns #Anzahl der Gewinner
for _, gr in df.groupby('IsMale'): #Halten Sie das Verhältnis nach Geschlecht konstant
m += lpSum(gr.Var) <= ns * len(gr) / nn + pena1
for _, gr in df.groupby('Div'): #Halten Sie das Verhältnis nach Abteilung konstant
m += lpSum(gr.Var) <= ns * len(gr) / nn + pena2
m.solve() #Lösung
addvals(df) #Ergebnis als Val-Spalte hinzufügen
print(df[df.Val > 0]) #Gewinner
Name | IsMale | Div | Rate | Score | Var | Val | |
---|---|---|---|---|---|---|---|
10 | Eriko Tominaga | False | Personalabteilung | 2 | 1.000000 | v000011 | 1.0 |
11 | Sato Tobita | False | Abteilung Allgemeine Angelegenheiten | 1 | 0.003906 | v000012 | 1.0 |
12 | Seito Kamiyama | True | Personalabteilung | 2 | 0.250000 | v000013 | 1.0 |
13 | Ryuichiro Tabata | True | Abteilung Allgemeine Angelegenheiten | 3 | 0.500000 | v000014 | 1.0 |
16 | Kiyoshiro Kasuga | True | Buchhaltung | 2 | 0.007812 | v000017 | 1.0 |
17 | Akisa Nakai | False | Buchhaltung | 3 | 0.062500 | v000018 | 1.0 |
19 | Yoshikatsu Kakinuma | True | Abteilung Allgemeine Angelegenheiten | 1 | 0.000122 | v000020 | 1.0 |
Die Gewinner stehen fest. Schauen wir uns die Anzahl der Personen nach Geschlecht und Abteilung an.
print(df[df.Val > 0].groupby('IsMale').Div.value_counts())
IsMale Div
Falsche Personalabteilung 1
Buchhaltungsabteilung 1
Abteilung für allgemeine Angelegenheiten 1
Abteilung für wahre allgemeine Angelegenheiten 2
Personalabteilung 1
Buchhaltungsabteilung 1
Name: Div, dtype: int64
Sieht gut aus.
――Eine Kombination, die verschiedene Bedingungen erfüllt, wird durch eine Methode erhalten, die als Kombinationsoptimierung bezeichnet wird.
(Ich persönlich hoffe, dass für diesen Artikel keine Nachfrage besteht.)
das ist alles
Recommended Posts