How to Schedule Tasks - algorithm

There is a carwash that can only service 1 customer at a time. The goal of the car wash is to have as many happy customers as possible by making them wait the least amount of time in the queue. If the customers can be serviced under 15 minutes they are joyful, under an hour they are happy, between 1 hour to 3 hours neutral and 3 hours to 8 hours angry. (The goal is to minimize angry people and maximize happy people). The only caveat to this problem is that each car takes a different amount of time to wash and service so we cannot always serve on first come first serve basis given the goal we have to maximize customer utility. So it may look like this:
Customer Line :
Customer1) Task:6 Minutes (1st arrival)
Customer2) Task:3 Minutes (2nd arrival)
Customer3) Task:9 Minutes (3rd)
Customer4) Task:4 Minutes (4th)
Service Line:
Serve Customer 2, Serve Customer 1, Serve Customer 4, Serve Customer 3.
In this way, no one waited in line for more than 15 minutes before being served. I know I should use some form of priority queue to implement this but I honestly know how should I give priority to different customers. I cannot give priority to customers with the least amount of work needed since they may be the last customer to have arrived for example (others would be very angry) and I cannot just compare based on time since the first guy might have a task that takes the whole day.So how would I compare these customers to each other with the goal of maximizing happiness?
Cheers

This is similar to ordering calls to a call center. It becomes more interesting when you have gold and silver customers. Anyway:
Every car has readyTime (the earliest time it can be washed, so it's arrival time - which might be different for each car) and a dueTime (the moment the customer becomes angry, so 3 hours after readyTime).
Then use a constraint solver (like OptaPlanner) to determine the order of the cars (*). The order of the cars (which is a genuine planning variable) implies the startWashingTime of each car (which is a shadow variable), because in your example, if customer 1 is ordered after customer 2 and if we start at 08:00, we can deduce that customer 1's startWashingTime is 08:03.
Then the endWashingTime is startWashingTime + washingDuration.
Then it's just a matter of adding 2 constraints and let the solver solve() it:
endWashingTime must be lower than dueTime, this is a hard constraint. This is to have no angry customers.
endWashingTime must be lower than startTime plus 15 minutes, this is a soft constraint. This is to maximize happy customers.
(*) This problem is NP-complete or NP-hard because you can relax it to a knapsack problem. In practice this means: you can't write an algorithm for it that scales out and finds the optimal solution in reasonable time. But a constraint solver can get you close.

Related

Algorithm development and optimization

I have this problem:
You need to develop a meal regime based on the data entered by the user. We have a database with the meals and their prices (meals also have a mark whether they are breakfast, cause on breakfast we eat smth different from lunch and dinner most often). The input receives the amount of money (Currency is not important) and the number of days. At the output, we must get a meal regime for a given number of days. Conditions:
Final price does not differ from the given one by more than 3%.
meals mustn't repeat more than once every 5 days.
I found this not effective solution: We are looking for an average price per day = amount of money / number of days. Then, until we reach the given number of days, we iterate throught each breakfast, then lunch and dinner (3 for loops, 2 are nested) and if price is not too different, then we end the search and add this day to the result list. So the design now looks like this:
while(daysCounter < days){
for(){
for(){
for(){
}
}
It looks scary, although there is not a lot of data (number of meals is about 150). There are thoughts that it is possible to find a more effective solution. Also i think about dynamic programming, but so far there are no ideas how to implement it.
Dynamic programming won't work because a necessary part of your state is the meals from the last 5 days. And the number of possibilities for that are astronomical.
However it is likely that there are many solutions, not just a few. And that it is easy to find a working solution by being greedy. Also that an existing solution can be improved fairly easily.
So I'd solve it like this. Replace days with an array of meals. Take the total you want to spend. Divide it up among your meals, in proportion to the median price of the options for that meal. (Breakfast is generally cheaper than dinner.) And now add up that per meal cost to get running totals.
And now for each meal choose the meal you have not had in the last 5 days that brings the running total of what has been spent as close as possible to the ideal total. Choose all of your meals, one at a time.
This is the greedy approach. Normally, but not always, it will come fairly close to the target.
And now, to a maximum of n tries or until you have the target within 3%, pick a random meal, consider all options that are not eaten within the last or next 5 days, and randomly pick one (if any such options exist) that brings the overall amount spent closer to the target.
(For a meal plan that is likely to vary more over a long period, I'd suggest trying simulated annealing. That will produce more interesting results, but it will also take longer.)

Even prize distribution

I'm currently facing interesting algorithm problem and I am looking for ideas or possible solutions. Topic seems to be common so maybe it's known and solved but I'm unable to find it.
So lets assume that I'm running shop and
I'm making lottery for buying customers. Each time they buy something they can win prize.
Prizes are given to customers instantly after buying.
I have X prizes and
I will be running lottery for Y days
Paying customer (act of buying, transaction) should have equal chance to win prize
Prizes should be distributed till last day (at last day there should be left some prizes to distribute)
There can not be left prizes at the end
I do not have historical data of transactions per day (no data from before lottery) to estimate average number of transactions (yet lottery could change number of transactions)
I can gather data while lottery is running
It this is not-solvable, what is closest solution?
Instant prize distribution have to stay.
Possible Solution #1
Based on #m69 comment
Lets says there are 6 prizes (total prizes) and 2 days of lottery.
Lets define Prizes By Day as PBD (to satisfy requirement have prizes till last day).
PBD = total prizes / days
We randomly choose as many as PBD events every day. Every transaction after this event is winning transaction.
Can be optimized to no to use last hour of last day of lottery to guarantee giving away all of prizes.
Pluses
Random. Simple, elegant solution.
Minuses
Seems that users have no equal chance to win.
Possible Solution #2
Based on #Sorin answer
We start to analyze first time frame (example 1 hour). And we calculate chance to win as:
where:
Δprizes = left prizes,
Δframes = left frames
What you're trying to do is impossible. Once you've gave away the last prize you can't prove any guarantee for the number of customers left, so not all customers will have equal chance to win a prize.
You can do something that approximates it fairly well. You can try to estimate the number of customers you will have, assume that they are evenly distributed and then spread the prizes over the period while the contest is running. This will give you a ratio that you can use to say if a given customer is a winner. Then as the contest progresses, change the estimates to match what you see, and what prizes are left. Run this update every x (hours/ minutes or even customer transaction) to make sure the rate isn't too low and every q prizes to make sure the rate isn't too high. Don't run the update too often if the prizes are given away or the algorithm might react too strongly if there's a period with low traffic (say overnight).
Let me give you an example. Say you figure out that you're going to see 100 customers per hour and you should give prizes every 200 customers. So roughly 1 every 2 hours. After 3 hours you come back and you see you saw 300 customers per hour and you've given out 4 prizes already. So you can now adjust the expectation to 300 customers per hour and adjust the distribution rate to match what is left.
This will work even if your initial is too low or too high.
This will break badly if your estimate is too far AND you updates are far in between (say you only check after a day but you've already given away all the prizes).
This can leave prizes on the table. If you don't want that you can reduce the amount of time the program considers the contest as running so that it should finish the prizes before the end of the contest. You can limit the number of prizes awarded in a given day to make the distribution more uniform (don't set it to X/Y, but something like X/Y * .25 so that there's some variation), and update the limit at the end of the day to account for variation in awards given.

A specific scheduling algorithm

The question I have concerns a hobby project that I'm working on to help out my wife with her work.
I realize that the problem I'm facing is quite similar to what's been answered on SO in numerous threads. However, I can't seem to find any thread that would address one little specific difference that I need to count in.
Here's a detailed description of the problem:
A teacher has numerous students that she teaches. Each student needs to have two lessons every week at least two days apart (i.e. Monday + Wednesday, Tuesday + Thursday etc.). The lessons are individual meaning there's only one student and the teacher in a class at a time. The teacher needs to have exactly one lunch break every day. The lunch break can be any time between two classes - the only condition is: a day cannot start or end in a lunch break. Each student provides their availability during a week (a list of possible time slots they can attend the class).
So far, this looks like a "regular" scheduling problem that there's bunch of material available online on.
But here's the catch: students are in different age meaning their lesson takes either 30 or 45 minutes. Younger students' lesson takes 30 minutes and olders' - 45 minutes. The goal of the algorithm is to find the optimal weekly schedule for the teacher. By optimal I mean a schedule where the teacher needs to spend least amount of time in school - all lessons back to back with no need for the teacher to wait for another student.
My first attempt was to come with all possible permutations of students' classes, lunch breaks and week days but for a 3 student schedule I came up with 13! permutations (that's roughly around 6 bln permutations). Here's why 13:
3 students - 2 classes each
4 lunch breaks (a 4 day week to keep the numbers small)
3 day breaks (a "night" so to speak)
The above gave me 13 elements to try in different permutations. However, after calculating the factorial I gave that up - 6 bln permutations will not be tried in any reasonable time on a "regular" machine. And that's just counting 3 students, the real-life data will be closer to 9 or 10. Obviously, the nonsense permutations (2 "nights" in a row, 2 classes for the same student on the same day and so on) would be thrown right away but still...
That was when I realized I'm not going to do this inventing the wheel by myself.
I did some research and came across Hopcroft-Karp algorithm. However I don't think it can be applied in a mixed timespan slots scenario (30/45 minute lessons). Am I wrong? Then I found some info on genetic algorithms. However, again I am not sure if they can take the mixed timespan condition into account?
I would greatly appreciate any pointers as to which directions my research should go.

A fast algorithm for determining timeshare requests

I am writing a program that will simulate how members of a certain timeshare will request their apartments. The apartments are only available for certain 'events' throughout the year, and the events each have different durations (counted in days). For each event, there are a number of apartments available, which are divided into groups according to cost (points per day).
We may also have the situation that some of the apartments are already rented out, so it is possible that certain events cannot admit a certain apartment type.
Now I want a member to request apartments according to this strategy:
Maximizing the number of total event days is first priority.
Maximizing the number of points spent is second priority (so the user requests the best possible apartment that he/she can afford and still have as many days as possible).
The total cost of the requested apartments cannot exceed the total amount of available points for that user.
Obviously, if there are no more apartments of a given type for a certain event, the user should not request that particular apartment/event combo.
I am wondering whether the problem is similar to the problem described here:
http://en.wikipedia.org/wiki/Hungarian_algorithm
in that it (I suppose) possible to frame this as a matrix problem where each entry has a cost associated with it.
However, the difference is that for my problem, I am allowed to use the same apartment for several events - it's not 'spent' once it has been used for one event. Also, the cost per entry is not really one-dimensional, since each event/apartment combo both has a number of days associated with it and a number of points - both of which should be maximized (but with priority given to the number of days).
As an example, let's say there are three apartment types, costing 75, 100, and 125 points per day, and three events, with a duration of 2, 10, and 4 days. Let's further say many of the apartments are taken, so the availability matrix looks like this:
cost
75 100 125
2 True False True
days 10 False False True
4 True False True
Let's also say the user has 1250 points available. The solution, in this case, would be that the user requests the 10-day event with the 125-point apartment and nothing else.
The brute-force way of doing this would perhaps be a recursive algorithm:
Let n be the number of events you are currently trying
Find all combinations of events and apartments, and calculate the combo that maximizes the number of days, then the number of points spent (this will both include all permutations of n events, but also the number of ways 3 apartment types can be assigned to n events).
Let n=n-1
This will quickly become overwhelming when the number of events goes up, I think, so I am wondering whether there are any algorithms that can solve this in a less expensive way?
If you have access to a library for http://en.wikipedia.org/wiki/Integer_programming you could try throwing this at it.
Even if you have only one choice of cost for each event, so that you are just trying to chose combinations of events that cover as many total days as possible without going over budget, I think this reduces to http://en.wikipedia.org/wiki/Knapsack_problem. This means that it is unlikely to be solved exactly by a worst case polynomial time algorithm such as the Hungarian algorithm.

Algorithm to find the best possible available times

Here is my scenario,
I run a Massage Place which offers various type of massages. Say 30 min Massage, 45 min massage, 1 hour massage, etc. I have 50 rooms, 100 employees and 30 pieces of equipment.When a customer books a massage appointment, the appointment requires 1 room, 1 employee and 1 piece of equipment to be available.
What is a good algorithm to find available resources for 10 guests for a given day
Resources:
Room – 50
Staff – 100
Equipment – 30
Business Hours : 9AM - 6PM
Staff Hours: 9AM- 6PM
No of guests: 10
Services
5 Guests- (1 hour massages)
3 Guests - (45mins massages)
2 Guests - (1 hour massage).
They are coming around the same time. Assume there are no other appointment on that day
What is the best way to get ::
Top 10 result - Fastest search which meets all conditions gets the top 10 result set. Top ten is defined by earliest available time. 9 – 11AM is best result set. 9 – 5pm is not that good.
Exhaustive search (Find all combinations) - all sets – Every possible combination
First available met (Only return the first match) – stop after one of the conditions have been met
I would appreciate your help.
Thanks
Nick
First, it seems the number of employees, rooms, and equipment are irrelevant. It seems like you only care about which of those is the lowest number. That is your inventory. So in your case, inventory = 30.
Next, it sounds like you can service all 10 people at the same time within the first hour of business. In fact, you can service 30 people at the same time.
So, no algorithm is necessary to figure that out, it's a static solution. If you take #Mario The Spoon's advice and weight the different duration massages with their corresponding profits, then you can start optimizing when you have more than 30 customers at a time.
Looks like you are trying to solve a problem for which there are quite specialized software applications. If your problem is small enough, you could try to do a brute force approach using some looping and backtracking, but as soon as the problem becomes too big, it will take too much time to iterate through all possibilities.
If the problem starts to get big, look for more specialized software. Things to look for are "constraint based optimization" and "constraint programming".
E.g. the ECLIPSe tool is an open-source constraint programming environment. You can find some examples on http://eclipseclp.org/examples/index.html. One nice example you can find there is the SEND+MORE=MONEY problem. In this problem you have the following equation:
S E N D
+ M O R E
-----------
= M O N E Y
Replace every letter by a digit so that the sum is correct.
This also illustrates that although you can solve this brute-force, there are more intelligent ways to solve this (see http://eclipseclp.org/examples/sendmore.pl.txt).
Just an idea to find a solution:
You might want to try to solve it with a constraint satisfaction problem (CSP) algorithm. That's what some people do if they have to solve timetable problems in general (e.g. room reservation at the University).
There are several tricks to improve CSP performance like forward checking, building a DAG and then do a topological sort and so on...
Just let me know, if you need more information about CSP :)

Resources