0

I am trying to create a program that create a schedule automatically based on 6 stores needs and 34 employee's availabilities. I am using python-constraint model to model the problem.

  • I wrote 2 constraints (each employee can only work 1 shift per day, each employee must be within their range of requested working days per week.
  • I have a dictionary where the values are store objects which contain the name of the store and the schedule.
  • The schedule is also a dictionary where the keys are the date in the format M AM (Monday Morning), where days are [M, T, W, R, F, S, U] and types of shifts are [AM, MID, PM].
  • The value of the schedule corresponds to the number of workers needed for said shifts (0, 1, or 2).
  • After this step, I will need another constraint to indicate employee's availabilities, but I will cross that bridge once I get there!

The current problem I am having is with constraint #3. Note that constraints 1 and 2 work perfectly and I have isolated constraint 3 for troubleshooting. When I run ONLY constraint 3 and ask for a solution I get None back.

I added a debugging statements which indicates that when the program is tasked to have either 0 or 2 workers assigned to said shift, it always puts 1 no matter what. I am not sure why this happening at all.

If anyone is familiar with python-constraint or even has suggestions on another module compatible with python that could work with this constraints problem, I'd greatly appreciate. Please note my code below as well as a sample output.

My Code

def constrain_model(stores_dict, employees_list, all_possible_shifts):
    problem = Problem()
    days = ['M', 'T', 'W', 'R', 'F', 'S', 'U']
## Constraint # 3 --> Each store has different shifts with different numbers of employees required on different days
    # stores_dict is a dictionary where key is the store name and the value is the store object
    # store objects have a name attribute (store.name) and a schedule attribute (store.schedule)
    # each store's schedule is a has a key with form f"{day} {shift}" indicating the day (M, T, W, R, F, S, U) and value is the number of people needed for that shift
    # some shifts have zero indicating this shift does not exist at this store
    # this constraint should enforce that the correct number of workers are assigned to each store's specific shifts
    # stores have either 0, 1, or 2 people on shifts as indicated in the value attributes of the entries in the schedule dictionary        

    # This code does not respond to 0 or 2 workers correctly, but the vars and constraints are correct!
    for store in stores_dict.values():
        for day in days:
            for shift in all_possible_shifts:
                assignment_var = f'{store.name}_{day}_{shift}_assigned'
                problem.addVariable(assignment_var, [0,1])

    for store in stores_dict.values():
        for day in days:
            for shift in all_possible_shifts:
                assignment_var = f'{store.name}_{day}_{shift}_assigned'

                def correct_number_of_employees_constraint(*assignments, day=day, shift=shift, store=store):
                    date = f'{day} {shift}'
                    print(f'{date} | {store.name} | {assignments} == {store.schedule[date]}')
                    print(sum(assignments), store.schedule[date])
                    return sum(assignments) == store.schedule[date]


                problem.addConstraint(correct_number_of_employees_constraint, [assignment_var])
     return problem



# Runner
stores_dict, employees_list = initialize_all_data()
all_possible_shifts = ["AM", "MID", "PM"]
problem = constrain_model(stores_dict, employees_list, all_possible_shifts)
print("I have the problem")
more = input("Do you want more information?")
if more == 'y':
    choice = input("vars or constraints or both")
    if choice == 'v' or choice == 'b':
        for variable in problem._variables:
            print(variable)
        print()
    if choice == 'c' or choice == 'b':
        for constraint in problem._constraints:
            print(constraint)
        print()
    print()
    
sol = input("Attempt a solution?")
if sol == 'y':
    a_solution = problem.getSolution()
    print(a_solution)
    print(problem.getSolver())

Sample Output:


OUTPUT KEY:
DAY SHIFT | STORE NAME | ASSIGNMENTS | == | REQUIRED NUMBER
CURRENT NUMBER ASSIGNMENTS | REQUIRED NUMBER ASSIGNMENTS


M AM | 87th | (0,) == 2
0 2
M AM | 87th | (1,) == 2
1 2
M MID | 87th | (0,) == 0
0 0
M MID | 87th | (1,) == 0
1 0
M PM | 87th | (0,) == 2
0 2
M PM | 87th | (1,) == 2
1 2

Note that in this output 87th is never assigned 2, only 1 before the program moves on (M AM)

Note that in this output 87th is assigned 1, despite needing 0 (M MID)

Thank you in advance for any help. If you other ideas for implementation in python, please let me know and of course if anyone knows python-constraint well -- please reach out!!

3
  • What you're showing us is not the final output. You're showing us intermediate outputs during the constraint callback. If you want detailed help, we need to see the actual input and the actual output -- something we can actually run. minimal reproducible example Commented Jan 23, 2024 at 19:05
  • The final output is just None because no solutions were found. I included only part of the output for brevity and relevance Commented Jan 23, 2024 at 20:05
  • But can you see there's not nearly enough information here for us to comment? We don't see the inputs. We don't see the list of employees. There's just not enough information. Commented Jan 23, 2024 at 20:09

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.