[PYTHON] Coordinator and integer linear programming

From the submitted adjustment, I formulated and solved the optimal combination of lunch parties as an integer linear programming.

I solved it with a python optimization package called PuLP.

This article is very easy to understand how to use PuLP. http://qiita.com/mzmttks/items/82ea3a51e4dbea8fbc17

Requirements

First, let's get the adjustment. TECH__MASTER_3月ランチ会___調整さん_と_pandas_get_dummies_—_pandas_0_19_2_documentation.png

** ・ Be sure to participate in some schedule per person ** ** ・ Equalize the number of people for each schedule as much as possible **

Let's do our best to formulate this.

First, $ P $ = (set of members) $ D $ = (set of dates) will do.

For $ p \ in P, d \ in D $

\mathrm{hope}[p][d] = \left\{
\begin{array}{ll}
1 & (p becomes d ○) \\
0 & (p becomes d ×)
\end{array}
\right.

And decide the constant from the result of Mr. Adjustment.

Then set the variables.

$ \ mathrm {attend} [p] [d] = (1or0) $ is a variable that indicates whether $ p $ actually participates in $ d $. $ M $ is the maximum number of participants for each schedule. By aiming to minimize this, it is possible to allocate a uniform number of people to each schedule.

When formulated, it looks like this.

\begin{align}
\mathrm{min} &\ M \\
\mathrm{s.t} \ &\forall d\in D\ \Sigma_{p \in P}\mathrm{hope}[p][d]\times \mathrm{attend}[p][d] \leq M \\
&\forall p\in P\ \Sigma_{d \in D}\mathrm{hope}[p][d]\times \mathrm{attend}[p][d] = 1

\end{align}

The first constraint is that the number of participants is M or less on each day. The second expression of the constraint is that each person must participate only once.

Let's do this hard.

code

chousei.py


import pulp

date = ["3/8", "3/9", "3/11", "3/15"]
people = #Put a list of member names here

_table = [
[1,1,1,1], 
[0,1,0,0],
[1,1,0,0],
[0,1,1,0],
[1,0,0,0],
[1,1,0,1],
[1,0,0,0],
[0,1,0,1],
[0,1,1,0],
[1,1,1,1],
[1,1,1,1],
[1,1,0,0],
[1,0,0,1],
[0,1,1,1],
[0,1,0,0],
[1,1,1,1]] #Write the result of Mr. Adjustment


table = {}
for i,p in enumerate(people):
    table[p] = {}
    for j,d in enumerate(date):
        table[p][d] = _table[i][j]
#Convert to dictionary type

problem = pulp.LpProblem('chousei', pulp.LpMinimize)
attend = pulp.LpVariable.dicts('attend', (people, date), 0, 1, 'Binary')
M = pulp.LpVariable('M', 0, 1000, 'Integer')
problem += M

for p in people:
    each_people = 0
    for d in date:
        each_people += table[p][d]*attend[p][d]
    problem += each_people == 1

for d in date:
    each_date = 0
    for p in people:
        each_date += table[p][d]*attend[p][d]
    problem += each_date <= M

problem.solve()

for d in date:
    each_date = ''
    for p in people:
        if(table[p][d] == 1 and attend[p][d].value() > 0):
            each_date += p
    print "{}: {}".format(d, each_date)

Improvement

At this rate, there is a possibility that only the elders will have a set schedule, so I think it's a good idea to give weight to each member and minimize the upper limit of the sum of the weights for each schedule. .. I will explain it when I feel like it.

Recommended Posts

Coordinator and integer linear programming
Linear Programming with PuLP
Programming with Python and Tkinter
Python real division (/) and integer division (//)
Linear programming + hands-on of pulp
Linear programming by Karmarkar's algorithm
List of Linear Programming (LP) solvers and modelers available in Python
[Introduction to Python3 Day 1] Programming and Python
Make let and let's one-line programming
Algebraic data types and object-oriented programming