Job sequencing with deadlines program in python

View Discussion

Improve Article

Save Article

  • Read
  • Discuss
  • View Discussion

    Improve Article

    Save Article

    Given an array of jobs where every job has a deadline and associated profit if the job is finished before the deadline. It is also given that every job takes a single unit of time, so the minimum possible deadline for any job is 1. Maximize the total profit if only one job can be scheduled at a time.

    Examples: 

    Input: Four Jobs with following deadlines and profits

    JobID  Deadline  Profit

      a           4          20   
      b           1          10
      c           1          40  
      d          1          30

    Output: Following is maximum profit sequence of jobs: c, a   

    Input:  Five Jobs with following deadlines and profits

    JobID   Deadline  Profit

      a            2          100
      b            1          19
      c            2          27
     d            1          25
     e            3          15

    Output: Following is maximum profit sequence of jobs: c, a, e

    Naive Approach: To solve the problem follow the below idea:

    Generate all subsets of a given set of jobs and check individual subsets for the feasibility of jobs in that subset. Keep track of maximum profit among all feasible subsets.

    Greedy approach for job sequencing problem:

    Greedily choose the jobs with maximum profit first, by sorting the jobs in decreasing order of their profit. This would help to maximize the total profit as choosing the job with maximum profit for every time slot will eventually maximize the total profit

    Follow the given steps to solve the problem:

    • Sort all jobs in decreasing order of profit. 
    • Iterate on jobs in decreasing order of profit.For each job , do the following : 
      • Find a time slot i, such that slot is empty and i < deadline and i is greatest.Put the job in 
        this slot and mark this slot filled. 
      • If no such i exists, then ignore the job. 

    Below is the implementation of the above approach:

    C

    #include <stdbool.h>

    #include <stdio.h>

    #include <stdlib.h>

    typedef struct Job {

        char id;

        int dead;

        int profit;

    } Job;

    int compare(const void* a, const void* b)

    {

        Job* temp1 = (Job*)a;

        Job* temp2 = (Job*)b;

        return (temp2->profit - temp1->profit);

    }

    int min(int num1, int num2)

    {

        return (num1 > num2) ? num2 : num1;

    }

    void printJobScheduling(Job arr[], int n)

    {

        qsort(arr, n, sizeof(Job), compare);

        int result[n];

        bool slot[n];

        for (int i = 0; i < n; i++)

            slot[i] = false;

        for (int i = 0; i < n; i++) {

            for (int j = min(n, arr[i].dead) - 1; j >= 0; j--) {

                if (slot[j] == false) {

                    result[j] = i;

                    slot[j] = true;

                    break;

                }

            }

        }

        for (int i = 0; i < n; i++)

            if (slot[i])

                printf("%c ", arr[result[i]].id);

    }

    int main()

    {

        Job arr[] = { { 'a', 2, 100 },

                      { 'b', 1, 19 },

                      { 'c', 2, 27 },

                      { 'd', 1, 25 },

                      { 'e', 3, 15 } };

        int n = sizeof(arr) / sizeof(arr[0]);

        printf(

            "Following is maximum profit sequence of jobs \n");

        printJobScheduling(arr, n);

        return 0;

    }

    C++

    #include <algorithm>

    #include <iostream>

    using namespace std;

    struct Job {

        char id;

        int dead;

        int profit;

    };

    bool comparison(Job a, Job b)

    {

        return (a.profit > b.profit);

    }

    void printJobScheduling(Job arr[], int n)

    {

        sort(arr, arr + n, comparison);

        int result[n];

        bool slot[n];

        for (int i = 0; i < n; i++)

            slot[i] = false;

        for (int i = 0; i < n; i++) {

            for (int j = min(n, arr[i].dead) - 1; j >= 0; j--) {

                if (slot[j] == false) {

                    result[j] = i;

                    slot[j] = true;

                    break;

                }

            }

        }

        for (int i = 0; i < n; i++)

            if (slot[i])

                cout << arr[result[i]].id << " ";

    }

    int main()

    {

        Job arr[] = { { 'a', 2, 100 },

                      { 'b', 1, 19 },

                      { 'c', 2, 27 },

                      { 'd', 1, 25 },

                      { 'e', 3, 15 } };

        int n = sizeof(arr) / sizeof(arr[0]);

        cout << "Following is maximum profit sequence of jobs "

                "\n";

        printJobScheduling(arr, n);

        return 0;

    }

    Java

    import java.util.*;

    class Job {

        char id;

        int deadline, profit;

        public Job() {}

        public Job(char id, int deadline, int profit)

        {

            this.id = id;

            this.deadline = deadline;

            this.profit = profit;

        }

        void printJobScheduling(ArrayList<Job> arr, int t)

        {

            int n = arr.size();

            Collections.sort(arr,

                             (a, b) -> b.profit - a.profit);

            boolean result[] = new boolean[t];

            char job[] = new char[t];

            for (int i = 0; i < n; i++) {

                for (int j

                     = Math.min(t - 1, arr.get(i).deadline - 1);

                     j >= 0; j--) {

                    if (result[j] == false) {

                        result[j] = true;

                        job[j] = arr.get(i).id;

                        break;

                    }

                }

            }

            for (char jb : job)

                System.out.print(jb + " ");

            System.out.println();

        }

        public static void main(String args[])

        {

            ArrayList<Job> arr = new ArrayList<Job>();

            arr.add(new Job('a', 2, 100));

            arr.add(new Job('b', 1, 19));

            arr.add(new Job('c', 2, 27));

            arr.add(new Job('d', 1, 25));

            arr.add(new Job('e', 3, 15));

            System.out.println(

                "Following is maximum profit sequence of jobs");

            Job job = new Job();

            job.printJobScheduling(arr, 3);

        }

    }

    Python3

    def printJobScheduling(arr, t):

        n = len(arr)

        for i in range(n):

            for j in range(n - 1 - i):

                if arr[j][2] < arr[j + 1][2]:

                    arr[j], arr[j + 1] = arr[j + 1], arr[j]

        result = [False] * t

        job = ['-1'] * t

        for i in range(len(arr)):

            for j in range(min(t - 1, arr[i][1] - 1), -1, -1):

                if result[j] is False:

                    result[j] = True

                    job[j] = arr[i][0]

                    break

        print(job)

    if __name__ == '__main__':

        arr = [['a', 2, 100], 

                  ['b', 1, 19],

                  ['c', 2, 27],

                  ['d', 1, 25],

                  ['e', 3, 15]]

        print("Following is maximum profit sequence of jobs")

        printJobScheduling(arr, 3)

    C#

    using System;

    using System.Collections.Generic;

    class GFG : IComparer<Job> {

        public int Compare(Job x, Job y)

        {

            if (x.profit == 0 || y.profit == 0) {

                return 0;

            }

            return (y.profit).CompareTo(x.profit);

        }

    }

    public class Job {

        char id;

        public int deadline, profit;

        public Job() {}

        public Job(char id, int deadline, int profit)

        {

            this.id = id;

            this.deadline = deadline;

            this.profit = profit;

        }

        void printJobScheduling(List<Job> arr, int t)

        {

            int n = arr.Count;

            GFG gg = new GFG();

            arr.Sort(gg);

            bool[] result = new bool[t];

            char[] job = new char[t];

            for (int i = 0; i < n; i++) {

                for (int j

                     = Math.Min(t - 1, arr[i].deadline - 1);

                     j >= 0; j--) {

                    if (result[j] == false) {

                        result[j] = true;

                        job[j] = arr[i].id;

                        break;

                    }

                }

            }

            foreach(char jb in job) { Console.Write(jb + " "); }

            Console.WriteLine();

        }

        static public void Main()

        {

            List<Job> arr = new List<Job>();

            arr.Add(new Job('a', 2, 100));

            arr.Add(new Job('b', 1, 19));

            arr.Add(new Job('c', 2, 27));

            arr.Add(new Job('d', 1, 25));

            arr.Add(new Job('e', 3, 15));

            Console.WriteLine("Following is maximum "

                              + "profit sequence of jobs");

            Job job = new Job();

            job.printJobScheduling(arr, 3);

        }

    }

    Javascript

    function printJobScheduling(arr, t){

        let n = arr.length;

        for(let i=0;i<n;i++){

            for(let j = 0;j<(n - 1 - i);j++){

                if(arr[j][2] < arr[j + 1][2]){

                    let temp = arr[j];

                    arr[j] = arr[j + 1];

                    arr[j + 1] = temp;

                }

             }

         }

        let result = [];

        let job = [];

        for(let i = 0;i<t;i++){

            job[i] = '-1';

            result[i] = false;

        }

        for(let i= 0;i<arr.length;i++){

            for(let j = (t - 1, arr[i][1] - 1);j>=0;j--){

                if(result[j] == false){

                    result[j] = true;

                    job[j] = arr[i][0];

                    break;

                }

            }

        }

        document.write(job);

    }

    arr = [['a', 2, 100], 

           ['b', 1, 19],

           ['c', 2, 27],

           ['d', 1, 25],

           ['e', 3, 15]];

    document.write("Following is maximum profit sequence of jobs ");

    document.write("<br>");

    printJobScheduling(arr, 3) ;

    Output

    Following is maximum profit sequence of jobs 
    c a e 

    Time Complexity: O(N2)
    Auxiliary Space: O(N)

    Job sequencing problem using Priority-Queue (Max-Heap):

    Sort the jobs in the increasing order of their deadlines and then calculate the available slots between every two consecutive deadlines while iterating from the end. Include the profit of the job at the root of the Max-Heap while the empty slots are available and Heap is not empty, as this would help to choose the jobs with maximum profit for every set of available slots.

    Follow the given steps to solve the problem:

    • Sort the jobs based on their deadlines.
    • Iterate from the end and calculate the available slots between every two consecutive deadlines. Insert the profit, deadline, and job ID of ith job in the max heap.
    • While the slots are available and there are jobs left in the max heap, include the job ID with maximum profit and deadline in the result.
    • Sort the result array based on their deadlines.

    Below is the implementation of the above approach:

    C++

    #include <bits/stdc++.h>

    using namespace std;

    struct Job {

        char id;

        int dead;

        int profit;

    };

    struct jobProfit {

        bool operator()(Job const& a, Job const& b)

        {

            return (a.profit < b.profit);

        }

    };

    void printJobScheduling(Job arr[], int n)

    {

        vector<Job> result;

        sort(arr, arr + n,

             [](Job a, Job b) { return a.dead < b.dead; });

        priority_queue<Job, vector<Job>, jobProfit> pq;

        for (int i = n - 1; i >= 0; i--) {

            int slot_available;

            if (i == 0) {

                slot_available = arr[i].dead;

            }

            else {

                slot_available = arr[i].dead - arr[i - 1].dead;

            }

            pq.push(arr[i]);

            while (slot_available > 0 && pq.size() > 0) {

                Job job = pq.top();

                pq.pop();

                slot_available--;

                result.push_back(job);

            }

        }

        sort(result.begin(), result.end(),

             [&](Job a, Job b) { return a.dead < b.dead; });

        for (int i = 0; i < result.size(); i++)

            cout << result[i].id << ' ';

        cout << endl;

    }

    int main()

    {

        Job arr[] = { { 'a', 2, 100 },

                      { 'b', 1, 19 },

                      { 'c', 2, 27 },

                      { 'd', 1, 25 },

                      { 'e', 3, 15 } };

        int n = sizeof(arr) / sizeof(arr[0]);

        cout << "Following is maximum profit sequence of jobs "

                "\n";

        printJobScheduling(arr, n);

        return 0;

    }

    Java

    import java.util.*;

    class GFG {

        static class Job {

            char job_id;

            int deadline;

            int profit;

            Job(char job_id, int deadline, int profit)

            {

                this.deadline = deadline;

                this.job_id = job_id;

                this.profit = profit;

            }

        }

        static void printJobScheduling(ArrayList<Job> arr)

        {

            int n = arr.size();

            Collections.sort(arr, (a, b) -> {

                return a.deadline - b.deadline;

            });

            ArrayList<Job> result = new ArrayList<>();

            PriorityQueue<Job> maxHeap = new PriorityQueue<>(

                (a, b) -> { return b.profit - a.profit; });

            for (int i = n - 1; i > -1; i--) {

                int slot_available;

                if (i == 0) {

                    slot_available = arr.get(i).deadline;

                }

                else {

                    slot_available = arr.get(i).deadline

                                     - arr.get(i - 1).deadline;

                }

                maxHeap.add(arr.get(i));

                while (slot_available > 0

                       && maxHeap.size() > 0) {

                    Job job = maxHeap.remove();

                    slot_available--;

                    result.add(job);

                }

            }

            Collections.sort(result, (a, b) -> {

                return a.deadline - b.deadline;

            });

            for (Job job : result) {

                System.out.print(job.job_id + " ");

            }

            System.out.println();

        }

        public static void main(String[] args)

        {

            ArrayList<Job> arr = new ArrayList<Job>();

            arr.add(new Job('a', 2, 100));

            arr.add(new Job('b', 1, 19));

            arr.add(new Job('c', 2, 27));

            arr.add(new Job('d', 1, 25));

            arr.add(new Job('e', 3, 15));

            System.out.println("Following is maximum "

                               + "profit sequence of jobs");

            printJobScheduling(arr);

        }

    }

    Python3

    import heapq

    def printJobScheduling(arr):

        n = len(arr)

        arr.sort(key=lambda x: x[1])

        result = []

        maxHeap = []

        for i in range(n - 1, -1, -1):

            if i == 0:

                slots_available = arr[i][1]

            else:

                slots_available = arr[i][1] - arr[i - 1][1]

            heapq.heappush(maxHeap, (-arr[i][2], arr[i][1], arr[i][0]))

            while slots_available and maxHeap:

                profit, deadline, job_id = heapq.heappop(maxHeap)

                slots_available -= 1

                result.append([job_id, deadline])

        result.sort(key=lambda x: x[1])

        for job in result:

            print(job[0], end=" ")

        print()

    if __name__ == '__main__':

        arr = [['a', 2, 100], 

               ['b', 1, 19],

               ['c', 2, 27],

               ['d', 1, 25],

               ['e', 3, 15]]

        print("Following is maximum profit sequence of jobs")

        printJobScheduling(arr)

    Output

    Following is maximum profit sequence of jobs
    a c e 

    Time Complexity: O(N log N)
    Auxiliary Space: O(N)

    It can also be optimized using Disjoint Set Data Structure. Please refer to the below post for details.
    Job Sequencing Problem | Set 2 (Using Disjoint Set)
     

    This article is contributed by Shubham. Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.


    How do you solve job sequencing with deadlines?

    Solution. To solve this problem, the given jobs are sorted according to their profit in a descending order. Hence, after sorting, the jobs are ordered as shown in the following table. From this set of jobs, first we select J2, as it can be completed within its deadline and contributes maximum profit.

    What is job sequencing with deadlines?

    In a job sequencing with deadlines problem, the objective is to find a sequence of jobs completed within their deadlines, giving a maximum profit. Let us consider the set of n given jobs associated with deadlines, and profit is earned if a job is completed by its deadline.

    What is job sequencing with example?

    Given a set of 9 jobs where each job has a deadline and profit associated to it . Each job takes 1 unit of time to complete and only one job can be scheduled at a time. We earn the profit if and only if the job is completed by its deadline.

    What are different methods of job sequencing?

    Since the scheduling may be done by using the rules of jobs and orders, two types of scheduling methodologies are created namely job-based rule and order-based rule.