Home>

I would like to create a shift using pulp.
Using the following data, I would like to create an objective function that minimizes the difference between the desired number of working days for part-time jobs and the actual number of working days.

#List of dates
day = pd.date_range ("2019-12-01", "2019-12-07")
#A set of part-time jobs
n_member = 10
member = pd.Series (f "member {i + 1}" for i in range (n_member))
#List of shifts
shift = (["9: 00-14: 00", "14: 00-19: 00", "19: 00-23: 00", "rest"])
# Desired attendance date
kibou = pd.DataFrame ([[1, 1, 1, 1, 1, 0, 0],
                      [1, 1, 1, 0, 0, 0, 1],
                      [0, 0, 0, 0, 0, 1, 1],
                      [0, 1, 1, 1, 1, 1, 0],
                      [1, 1, 1, 1, 1, 1, 1],
                      [1, 1, 1, 1, 1, 1, 1],
                      [1, 1, 1, 0, 0, 0, 0],
                      [0, 0, 0, 0, 1, 1, 1],
                      [0, 1, 1, 1, 1, 1, 0],
                      [1, 1, 1, 0, 1, 0, 0]],
                     index = member,
                     columns = day)


I created the following program, but an error occurred.

# Create model
prob = LpProblem (sense = LpMinimize)
#variable
x = [[[LpVariable (f "x {m} {d} {t}", cat = LpBinary) for t in shift]
     for d in day] for m in member]
#Objective function
obj = 0
for m in range (member.size):
        # Desired attendance days
        ks = kibou.sum (axis = 1)
        #Actual days worked
        actual = lpSum (x [m] [j] for j in range (day.size))
        #Difference between the desired number of working days and the actual number of working days
        obj = ks-actual
        # (Restriction 1) Constraint that the actual working days do not exceed the desired number of working days
        prob + = actual<= ks
prob + = obj

TypeError: Can only add LpConstraintVar, LpConstraint, LpAffineExpression or True objects

Please tell me how to create a model.

  • Answer # 1

    ks = kibou.sum (axis = 1), the variableksis a Series object, not an integer.
    Shouldn't we calculate the total number of working days for each member asks = kibou.iloc [m] .sum ()?

    code
    import pandas as pd
    from pulp import LpBinary, LpMinimize, LpProblem, LpVariable, lpSum
    # List of dates
    day = pd.date_range ("2019-12-01", "2019-12-07")
    # List of part-time jobs
    n_member = 10
    members = pd.Series (f "member {i + 1}" for i in range (n_member))
    # List of shifts
    shift = ["9: 00-14: 00", "14: 00-19: 00", "19: 00-23: 00", "rest"]
    # Desired attendance date
    kibou = pd.DataFrame (
        [
            [1, 1, 1, 1, 1, 0, 0],
            [1, 1, 1, 0, 0, 0, 1],
            [0, 0, 0, 0, 0, 1, 1],
            [0, 1, 1, 1, 1, 1, 0],
            [1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 1, 1, 1],
            [0, 1, 1, 1, 1, 1, 0],
            [1, 1, 1, 0, 1, 0, 0],
        ],
        index = members,
        columns = day,
    )
    # Create model
    prob = LpProblem (sense = LpMinimize)
    # Variable (members, shift, day)
    x = [
        [[LpVariable (f "x {m} {d} {t}", cat = LpBinary) for t in shift] for d in day]
        for m in members
    ]
    # Objective function
    obj = 0
    for m in range (members.size):
        # Desired attendance days
        ks = kibou.iloc [m] .sum ()
        # Days actually worked
        actual = lpSum (x [m] [j] for j in range (day.size))
        # Difference between desired working days and actual working days
        obj = ks-actual
        # (Restriction 1) Restriction that the actual working days do not exceed the desired number of working days
        prob + = actual<= ks
    prob + = obj
    print (prob)
    prob.solve ()

Trends