1

I'm trying to program the interval scheduling problem with dynamic programming. All jobs have different (positive) weights and don't overlap. These weights represent different run times. An idle time of three "gaps" may exist between jobs. Furthermore, each time unit for each job (in seconds) takes one resource. The resources can all have different values. I want to find the smallest sum of resources for all jobs with a dynamic programming algorithm (recursively).

It may be more clear with an example:

Let's say you have three jobs with time units { 2, 2, 3 } and you have a list of resources of eight long { 2, 5, 1, 8, 4, 1, 1, 5 }. Job one takes two time units and thus two resources, and because it's the first job it will take the first 2 resources of the resources-list. Job two doesn't have to start immediately after job one, it can also start from one of the next three "gaps". This second job takes also two resources and because it can start from one of the three gaps and it's not the first job, the possibilities of resources that it can take are (1,8) (8,4) (4,1) (1,1) = 9 12 5 2 (the different sums of the available resources). The sum of all jobs is of course less than the number of resources.

This is continued until all jobs are finished. I want to find the smallest sum of resources for all jobs with a dynamic programming algorithm (recursively).

I tried different solving methods, but I find this one very hard to solve recursively without any other function.

I did write the following code, which is not doing as I expected:

public static double getCost(int t, int q, int r, int[] jobs, double[] resources){
    double table[][] = new double[t+1][r+1];
    for(int i = 0;i < t;i++){
        for(int j = 0;j < r;j++){
            double cost = 0;
            for(int k = j-jobs[i] + 1;k <= j;k++){
                if(k < 0){
                    break;
                }
                cost = cost + resources[k];
            }
            double min = Double.POSITIVE_INFINITY;
            for(int l = 1;l <= q;l++){
                if(i == 0 && l == 1){
                    min = cost+j-jobs[0]-l;
                }
                else{
                    double neww = cost+j-jobs[i]-l;
                    if(neww < min){
                        min = neww;
                    } 
                }
            }
            table[i+1][j+1] = min;
        }
    }
    return table[t][r];
}

Can someone please give me some advice?

n00b1990
  • 1,189
  • 5
  • 17
  • 25

1 Answers1

3

First, you need to define the state for each subproblem, so:

sum[t][r] = Minimum cost using up to 't' indexes in 'timeUnits',
            and 'r' indexes in 'resources' (exclusive indexes).

The base case is:

sum[0][0] = 0

Then update the array values based on previous values. There are two things to calculate: the cost of running a job, and what to add it on to (gap size).

For each t
  For each r
    cost = Sum(resources[i]) for i = r-timeUnits[t]+1 ... r
    sum[t+1][r+1] = Min(cost + sum[t][r-timeUnits[t]-gap+1]) for gap = 0 ... 2 (0 only for t=0)

The final cost is the minimum value where all time units are used.

Edit: I modified your code so that it passed your test case.

int[] jobs = { 2, 2, 2 };
int[] resources = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 1 };
int q = 2;
int t = jobs.length;
int r = resources.length;

double table[][] = new double[t+1][r+1];

for(int i = 0;i <= t;i++){
    for(int j = 0;j <= r;j++){
        table[i][j] = Double.POSITIVE_INFINITY;
    }
}
table[0][0] = 0;

for(int i = 0;i < t;i++){
    for(int j = 0;j < r;j++){
        double cost = 0;
        for(int k = j-jobs[i] + 1;k <= j;k++){
            if(k < 0){
                cost = Double.POSITIVE_INFINITY;
                break;
            }
            cost = cost + resources[k];
        }

        double min = Double.POSITIVE_INFINITY;
        for(int l = 0;l <= q;l++) {
            int index = j-jobs[i]-l+1;
            if(index >= 0 && index <= r) {
                min = Math.min(min, cost + table[i][index]);
            }
            if(i == 0) break;
        }

        table[i+1][j+1] = min;
    }
}

double best = Double.POSITIVE_INFINITY;
for(int x = 0; x < r; x++) {
    best = Math.min(best, table[t][x+1]);
}

System.out.println("Best cost: " + best);
fgb
  • 18,439
  • 2
  • 38
  • 52
  • Hi, thanks for your help. The solution you provided looks like an iterative one, which is no problem. The rule r-timeUnits[t]+1 ... r, what do you mean by this? Something like loop from i = r-timeUnits[t]+1 to r? where r is the amount of indexes in resources? Or for each r? Again, thank you for the help I appreciate it. – n00b1990 Dec 21 '12 at 21:26
  • @n00b1990 You're using timeUnits[t] resources - starting at resources[r-timeUnits[t]+1] and ending at resources[r], so use a for-loop to add up these resource values. – fgb Dec 21 '12 at 23:42
  • I do use a for-loop, the only problem is when r is zero, which stands for the first column. I would get i = 0-timeUnits[t] + 1. If timeUnits[t] > 1 I would get a problem because of a negative index, at least that's what I have? – n00b1990 Dec 22 '12 at 10:43
  • @n00b1990 Check the indexes first. If any are out of bounds, then skip these iterations. – fgb Dec 22 '12 at 17:45
  • I added my implementation if you would like to take a look at my code. There is yet one thing with the current algorithm: the minimum cost of a specific job is not always the minimum sum of the interval q (gaps). For example if you have the sequence of jobs { 2, 2, 2 } and we have resources { 1, 2, 3, 4, 5, 6, 7, 8, 1, 1 } and we can have 2 gaps. The current algorithm takes the minimum for every summation (1,2), (3,4) and (5,6) = 3 7 11 = 21 total resources. It would be better if the algorithm chose (1,2), (5,6) and (1,1) = 3 11 2 = 16 total resources. Can you help me on this? Thank you. – n00b1990 Dec 24 '12 at 19:51
  • Hi, thank you for your help, the code you provided is indeed working as I wanted to. I see that you're iterating through the last row to get the optimal cost, am I right? I'm curious, what is your approach to solve these kind of algorithms? Some extra hints would be great. And thank you for taking the time to help me, I really appreciate it :) – n00b1990 Dec 24 '12 at 23:32
  • Yes, check the whole last row if the jobs don't need to end on the last resource. I defined the contents of the table array first - the basic structure is similar to other dynamic programming problems. I break the problem down into small steps and get simple cases working first. Manually figure out what the values for [0][0], [0][1], [1][0], [1][0] should be and try to get these right first, then keep adding more test cases. – fgb Dec 25 '12 at 00:57
  • Maybe a little late, but I wanted to thank you for your help, the problem is fixed. Thank you very much! – n00b1990 Jan 02 '13 at 18:08