I have Job Sequencing Problem with three parameters where every task has time to be completed(in weeks) and a deadline that mush be finished before it.
In other words, any week, Job can be worked on at most. All jobs have a hard deadline, which means they must be completed before the deadline. The task is to arrange the jobs so that a high profit shall be accumulated.
Example
Input:
JobID Time Profit Deadline
1 8 100 13
2 1 100 1
3 1 100 3
4 1 100 2
5 4 100 6
Output
Total profit: 400
Jobs in order: 2 4 3 1
I have been trying to apply greedy algorithm but it only works with two parameters(profit & deadline) but here I have to take time into consideration
The solution can be obtained through dynamic programming. Before diving into the recursion, something to develop the intuition:
(I'm assuming any task will start no earlier than the earliest date in the deadline. That is, for your example, it would be day 1.)
Let D_i denote the time in days it takes to complete Task (or job) T_i. Denote the profits for task T_i as P_is.
On a calendar day C (the hypothetical calendar starting on earliest day of the deadline), you can be doing only one task per the problem definition. It could be one of T_1, T_2, T_3, T_4 or T_5.
If you were doing task T_1 on day C, it means that you started the task on C - D_1 day of the calendar. Similarly, if you were doing task T_2 on day C, then you started on the task on day C - D_2, and so on.
You could be doing any one of the tasks T_1, T_2, T_3, T_4 or T_5 on day C. Therefore, the profit you get by doing the last task in the sequence on day C is one of P_1, P_2, P_3, P_4 or P_5. If you add the profit of Task T_i that you were doing on the last day (i.e. P_i) to the maximum profit until day C - D_i, not including that task, for each 1<= i <= 5, you'll get the set of maximum profits you could possibly make on day C. The highest among these profits is what you're looking for. In the end, the answer would be the solution for day 13. (C = 13)
(I've tweaked your example a slight bit for more generality)
I'll leave it up to you to figure out how to codify this into a programming construct. On a broad level, you'll need two variables for your dynamic programming recursion:
Set of tasks (i.e., modeling T_i)
Calendar Days (i.e., modeling C)
Prioritize the jobs by profit per unit of time, breaking ties for the one that finishes first.
In other words think of it as dollars per hour and work on the job that pays you fastest.
JobID Time Profit Deadline Priority
1 8 100 13 12.5
2 1 100 1 100
3 1 100 3 100
4 1 100 2 100
5 4 100 6 25
And now we look at jobs 2, 4, 3, 5, then 1 in that order. We can do the first three and the last.
Related
I recently came across a this question in a forum:
You are given a straight line starting at 0 to 10^9. You start at zero and there are n tasks you can perform. i th task is located at point i in the line and requires 't' time to be performed. To perform the task you need to reach the point i and spend 't' time at that location.
example: (5,8) lies at 5 so travel distance is 5 and work effort is 8.
Total effort is calculated as travel distance + time required to complete the work.
It takes one sec to travel one unit of path.
Now we are given total T seconds and we need to complete as many tasks as possible and reach back to starting position
Find the max number of tasks that you can finish in time T.
example :
3 16 - 3 tasks and 16 units of total time
2 8 - task 1 at position 2 in line and takes 8 sec to complete
4 5 - task 2 at position 4 in line and takes 5 sec to complete
5 1 - task 3 at position 5 in line and takes 1 sec to complete
Output : 2
Explanation :
If we take task 1 at location 2 which requires 8 sec then getting to location 2 takes 2s and completing the task takes 8s leaving us with only 6s which is not enough for completing other task
On the other hand skipping the fist task leaves us enough time to complete the other two tasks.
Going to location and coming back costs 2x5 =10s and performing task at location 4 and 5 cost us 5+1 = 6s. Total time spent will be 10s+6s=16s.
I am new to graphs and DP so I was not sure which approach to use Hamiltonian cycle, Knapsack or Longest Path.
Can someone please help me with the most efficient approach to solve this.
Let's iterate from the first task to the last, according to distance. As we go, it's clear that after subtracting 2 * distance(i) + effort(i) for considering the current task as our last, the most tasks we can achieve can be found by greedily accumulating as many earlier tasks as possible into the remaining time, ordering them by increasing effort.
Therefore, an efficient solution could insert the seen element into a data-structure ordered by effort, dynamically updating the best solution so far. (I originally thought of using a treap and binary search but j_random_hacker suggested a much simpler way in the comments below this answer.)
Suggestion:
For each task n create a graph like this
Join up these graphs for all the tasks.
Run a travelling salesman algorithm to find the minimum time to do all the tasks ( = visit all the nodes in combined graph )
Remove tasks in an orderly sequence. This will give you a collection of results for different numbers of tasks performed. Choose the one that does the most number of tasks that still remains under the time limit.
Since you are maximizing the number of tasks performed, start by removing the longest tasks so that you will be left with lots of short tasks.
Assume you are given t1, t2, t3, ..., tn amount of tasks to finish every day. And once you start working, you can only finish c1, c2, c3, ..., cn tasks until spending 1 day resting. You can spend multiple days resting too. But you can only do the tasks which are given you that day. For example;
T[] = {10, 1, 4, 8} given tasks;
C[] = {8, 4, 2, 1} is the capacity of doing tasks for each day.
For this example, optimal solution is giving a break on the 3rd day. That way you can complete 17 tasks in 4 days:
1st day 8 (maximum 10 tasks, but c1=8)
2nd day 1 (maximum 1 task, c2=4)
3rd day 0 (rest to reset to c1)
4th day 8 (maximum 8 tasks, c1=8)
Any other schedule would result with fewer tasks getting done.
I'm trying to find the recurrence relation for this dynamic programming problem. Can anyone help me? I find this question but mine is different because of the decreasing work capacity and there are different number of jobs each day. Reference
If I got you right you have an amount of tasks to do, t(i) for every day i. Also you have some kind of a given internal restriction sequence c(j) for a current treak day j where j can be reseted to 0 if no task was done that day. Goal is to maximizie the solved tasks.
Naive approach is to store for each day i a list for every state j how many tasks were done. Fill the data for the first day. Then for every following day fill the values for the "no break" case - which is
value(i-1,j-1)+min(t(i),c(j)). Choose the maximum from the previous day to fill the "break" entry. Repeat until last day. Choose the highest value and trace back the path.
Example for above
Memory consumtption is pretty easy: O(number of days * number of states).
If you are only interested in the value and not the schedule the memory consumption would be the O(number of states).
Time consumption is a bit more complex, so lets write some pseudo code:
For each day i
For each possible state j
add and write values
choose maximum from previous day for break state
choose maximum
For each day
trace back path
The choose maximum-function would have a complexity of O(number of states).
This pseudo code results in time consumption O(number of days * number of states) as well.
What is the best approach to take if I want to find the minimum total cost if I want to assign n jobs to a person in a sequence which have cost assigned to them? For eg. I have 2 jobs which have costs 4 and 5 respectively. Both jobs take 6 and 10 minutes respectively. So the finish time of the second job will be finish time of first job + time taken by this job. So the total cost will be finish time of each job multiplied by its cost.
If you have to assign n jobs to 1 person (or 1 machine) in scheduling literature terminology, you are looking to minimize weighted flow time. The problem is polynomially solvable.
The shortest weighted processing time sequence is optimal.
Sort and reindex jobs such that p_1/w_1 <= p_2/w_2 <= ... <= p_n/w_n,
where, p_i is the processing time of the ith job and w_i is its weight or cost.
Then, assign job 1 first, followed by 2 and so on until n.
If you look at what happens if you swap two adjacent values you will end up comparing terms like (A+c)m + (A+c+d)l and (A+d)l + (A+c+d)m, where A is the time consumed by earlier jobs, c and d are times, and l and m are costs. With some algebra and rearrangement you can see that the first version is smaller if c/m < d/l. So you could work out for each job the time taken by that job divided by its cost, and do first the jobs with smallest time per unit cost. - check: if you have a job that takes 10 years and has a cost of 1 cent, you want to do that last so that 10 year wait doesn't get multiplied by any other costs.
The Problem is: Imagine a student has n projects and m hours to do the projects. He has to manage his time to get the maximum points that he can get.
By working 1 hour on each project he can catch different points.
For example by working one hour on project 1, he can get 2 point and if he work two hours on project 1 he can get 2.25 points.
Project 2 is different - by working 1 hour on project 2, he can get 1 point, but by working two hours on it he can catch 2.5 points.
Another Example:
m = 5 and n = 10. means that there are 5 projects and 10 hours time to do the projects.
projectnumber hours to complete 1 hour work 2h work 3h work 4h work
1 3 1.5 2 2.25 _
2 4 0.5 1.75 2 2.25
3 3 2 2.25 2.5 _
4 2 1 2 _ _
5 5 1 2 2.5 3
What I could understand:
After thinking about this, I understood it's like job scheduling and maybe the best algorithm for this problem is a dynamic programming algorithm.
At first you should consider the first hour of projects. and sort it by profit descending.
2 1.5 1 1 0.5
After doing the first hour of project 3, you should add the second hour of project 3 to the list (9 hours remain).
1.5 1 1 0.5 0.25 (0.25 is for second hour of project 3)
And it should continue till the end of the 10 hours time that you have to do the projects.
But I'm sure this algorithm has some problems. One of them is that, maybe the second hour of a project causes you to catch a good point. So you can not just consider the first hour of projects.
Any suggestions?
Your problem seems similar to the 0-1 knapsack problem :-
Total hours m is that knapsack capacity
consider each number of hours and corresponding points as an item weight and value
Maximize the points.
0-1 Knapsack problem as DP solution in pseudo polynomial time.
Formulation of problem for Nth project :-
Knapsack(N,M) = max(Knapsack(N-1,M),Knapsack(N-1,M-1)+Points[N][1]+Knapsack(N-1,M-2)+Points[N][2]......)
Note:- Points[N][k] = points earns by working k hours on project N
Knapsack Problem
Here is the problem. Suppose we have N workers and N jobs. We want to assign each job exactly one worker. For each worker i, he could do some jobs on some cost. Our goal is to minimize the total cost on the condition that any single cost should be less than some value.
For example, 10 workers and 10 jobs. Worker 1 can do job 1 with $0.8, job 2 with $2.3, job 3 with $15.8, jobs 4 to 8 with $100, job 9 with $3.2, job 10 with $15.3.
Worker 2 can do job 1 with $3.5, job 2 with $2.3, job 3 with $4.6, job 4 with $17, etc.
Our goal is to find a matching or we can call it an assignment such that the total cost is minimized but any single cost of the corresponding pair/matching between work i and job i is less than a value like $50.
I would very much like to solve it in MATLAB if possible.
This is a slight variation of the Assignment Problem. To handle your additional constraint that no single job cost should be more than some value, just change all entries in the matrix of costs that are greater than this threshold to a huge value (bigger than the sum of all other entries will suffice), and solve as usual, using e.g. the Hungarian Algorithm.