13

I am working on a PHP application for an at home care company. They have x amount of carers that are scheduled every week to attend the houses of x amount of service users (clients). Each service user has a set 'schedule' of when they are to be visited which includes periods plus the visit duration in minutes.

So for example, a service user could have the following schedule.

      AM   Lunch   Tea   Late   Night   Respite
Mon   30m  -       30m   60m    -       -
Tue   30m  -       -     60m    -       -
Wed   20m  25m     30m   60m    120m    -
Thu   -    -       30m   -      -       -
Fri   30m  25m     -     -      -       -
Sat   -    -       -     -      -       -
Sun   20m  25m     -     -      -       -

These periods are currently stored in a database in the following format:

Table: Service_user_schedules
id   service_user_id   day   period   duration

Every week, the carers fill out a table of what periods they are available to work. This data is then input into the system and is stored in the database in the following format:

Table: Carer_available_shifts
id   carer_id   day   period

Now the problem is, I need to create a controller that will take this data and automatically assign carers to service users based on the availability they have supplied. This needs to be editable so that in the event that nobody is available for a particular carer, the user can select one that isn't available and they will still be added to the database.

At the moment, I have a mess of loops, functions and echo's to check if carers are available for a particular service user and to make it editable.

Has anyone performed this sort of task before and if so, did you find a simple way to complete it. I would prefer to make it object orientated so I could reuse the same generic class but at the moment, I'm at a complete loss!

EDIT: I have now added a bounty to this question. I am currently researching genetic algorithms (something that I have never even heard of let alone used!) as a solution to this problem based on some of the answers. I would like to know if any of you have used other methods of solving this type of problem or if you have used genetic algorithms, could you provide a less general explanation on how you applied them to this particular issue.

I would assume that this hurdle would be fairly common in many "staffing" type applications and am surprised at how little discussion there is on this anywhere on the web!

UPDATE

For this particular project, I think I may end up using the database method as described by Tak but may possibly convert to the use of GA's in the future when I have more development time set aside.

I am now at a bit of a loss as to who to award the bounty to. duedl0r put alot of effort into his (or her) answer. It has given me a great insight into the world of Genetic Algorithm's - a problem solving method that I had never come across before. However, the answer provided by Tak provides the solution that I will be using for this project. Therefore, I have awarded the bounty to Tak.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Daniel Greaves
  • 987
  • 5
  • 24
  • 1
    is it timestamp by any chance? – Daniel Greaves Jun 29 '11 at 12:22
  • 3
    I'll be honest dave, I have no idea what you're on about :D – Daniel Greaves Jun 29 '11 at 12:29
  • I wrote such an application in C#, as kind of a portfolio project. I used genetic algorithm. I'd had no prior professional experience but I didn't find it very difficult. My presentation (and links to source code) - http://vimeo.com/20610875 I will elaborate when I'm back from work (I am NOT posting this as a job-hunting move, I'm working already and in a different country; I just happened to never take the video off. so I hope I'm not violating any rules by posting that here.) – Konrad Morawski Jul 05 '11 at 10:19
  • You said you want it to be automatic, but do you want it to do it automatically on event creation or run as a cron job every day? The difference being would be looping through all of them (as in the cron job) or grabbing the first available (as in the event creation). – Patrick Jul 06 '11 at 16:58

3 Answers3

3

Sounds like the employee shift rostering problem, which is NP-complete.

If you think metaheuristics (such as genetic algorithms, tabu search, simulated annealing, ...) is overkill, then just go for a simple First Fit Decreasing algorithm.

Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120
  • This sounds interesting. Unfortunately, I know absolutely nothing about genetic algorithms so this could be a very steep learning curve. However, I would be keen to learn more about them. With regards to the simple first fit decreasing algorithm whereby the elements are first sorted in ascending order (for example size in a bin packing problem), how would this relate to the scheduling of staff? – Daniel Greaves Jul 01 '11 at 22:03
  • Sort them by decreasing difficulty (so size in bin packing), which in staff scheduling means by decreasing number of shifts at the same time (possibly summing 1 + the number of employees that cannot service each shift) – Geoffrey De Smet Jul 04 '11 at 20:06
  • Here is [a First Fit Decreasing implementation of nurse rostering in Java with Drools Planner (apache license)](https://github.com/droolsjbpm/drools-planner/blob/master/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/solution/initializer/NurseRosteringStartingSolutionInitializer.java). – Geoffrey De Smet Jul 04 '11 at 20:08
2

Maybe you can use a genetic algorithm. This has the advantage that you can do really crazy stuff (if you have set up the basics), e.g. you could also say that a carer should optimally visit a service user he used to visit before, or minimize the distance between visits :)

Doing it like that every service user gets a carer even if there is no available schedule. The algorithm just tries to create a optimal solution..

Probably it's a bit overkill, but it's an interesting topic.. :) I wanted to mention it because it may be a new way to tackle your problem. At least worth a thought ;)

Some Links: Genetic Algorithm Resource, Genetic Algorithm Tutorial, Wikipedia


Edit: More concrete explanation of genetic algorithms.

A genetic algorithm consists of modelling the theory of evolutionary development. Evolutionary development needs a population of certain creatures. Then you simulate the development of the population using certain biological effects like mutation, selection, crossing etc.. Like darwin found out a few years ago :)

Now you have to map your problem to such a creature (or a DNA). This means every creature represents a solution in your problem space (every DNA is a solution to your problem).

So the phrase "survival of the fittest" just means "I get a solution to my problem which might be optimal" (not guaranteed though).

A mapping from your problem to such a DNA can be done very differently. First you need an array to represent your DNA. You can specify for example this:

You create chunks of 42 elements for every service user (6 slots per day, 7 days a week). Then your first entry in the array is the "AM"/Mon slot for service user 1. Your second entry the "Lunch"/Mon slot for service user 1. Your 43th entry is the "AM"/Mon slot for service user 2. This defines the DNA of your creature. Then you let them hump each other so they can develop :)

In order to find out which creature is well fitted, you also need a formula which calculates the fittness. You create a formula which has a DNA as input and a number as output. This is depending on your rules. For example you can give some plus or minus points if there are certain rules holding or not. If a carer is used for two different service user at the same time you give some minus points, if a carer has actually time for a slot and he is really scheduled for a service user you can give plus points.

You can also say: A genetic algortihm tries to find out how to maximize this formula using a genetic approach.

Very short introduction to genetic algorithms..if you have enough time and if you're also interested in the topic it's really worth digging into it.. you can some really cool stuff with it. But keep in mind, it can get also messy and complicated :)

Community
  • 1
  • 1
duedl0r
  • 9,289
  • 3
  • 30
  • 45
  • Hmm, I've never heard of genetic algorithms before. It sounds a bit overkill but I will definitely take a look. I can't seem to find much documentation on them though, could you point me in the right direction? – Daniel Greaves Jun 29 '11 at 12:33
  • Added in the answer, however, I'm not sure whether they are suitable, if you've never heard of it. Tell me if you need some more hints.. – duedl0r Jun 29 '11 at 12:39
  • As interesting as GA's are I feel that it is most definitely overkill and probably not going to solve the problem. GA's can be useful in a domain with an unknown solution eg its not immediately obvious how to solve the problem. In this scenario there is an algorithm for how to solve teh problem (its complex but it has a set of well defined rules. A GA here would be an unnecessary complication. – Toby Allen Jul 03 '11 at 09:07
  • @Toby Allen: yes you're right that it's probably overkill. But I'm sure it will give good results if it's implemented properly. Of course there are disadvantages and advantages. If you set up this approach you have a lot of flexibility. You can change rules and behaviours. You might not be able to do that using an algorithm which just solves this problem as is. Why don't you show us your algorithm? :) – duedl0r Jul 05 '11 at 09:58
  • added an explanation to genetic algorithms in my post – duedl0r Jul 05 '11 at 09:58
1

I'd approach it like this. First a database table that links schedule slots to available carers...

Table schedules_shifts
id   service_user_schedules_id   carer_available_shifts_id

Now a function that matches available carers to required schedule slots and populates the table...

* Fetch service_user_schedules for the next week
* For each service_user_schedules row
 * Fetch carer_available_shifts that match the schedule slot
 * For each carer_available_shift row
  * If results
   * Fetch schedules_shifts rows where carer_available_shifts_id is already used
   * If no results
    * Insert a row in the schedules_shifts table for each carer
   * Otherwise carer is busy, do nothing and continue
  * If no results, flag for review or trigger e-mail to manager, or other action
* Trigger e-mail or save log of completion for peace of mind

The new table now has possible carer matches for schedule slots with no duplicate allocation of a carer's time. It does however match multiple carer's shifts with a schedule slot. This could be a feature! Leave them as-is and add a confirmed column on schedules_shifts so a manager can manually assign the work, or carers can volunteer, or automatically mark the first match as confirmed and keep the other rows as alternatives in case the first carer can't make it.

This can all be triggered by a cron every week, or when the final career updates their week's schedule. Probably the first because users are often unpredictable.

Now the automated data is in a table you can open it up for editing. Create a normal admin console as you would to change the rows in schedules_shifts as appropriate, or flag different rows "confirmed".

Translating it into a generic class shouldn't be too difficult - just a matter of using generic terminology. It's late and I can't think of any though :)

It's possible to do all the data sifting in PHP arrays rather than the database dance I've created above, but I think SQL is more appropriate for sorting through the data and making amendments.

Genetic algorithms sound interesting though, and if you've got the time investigate them ^_^

Hope that helps?

Tak
  • 11,428
  • 5
  • 29
  • 48