Open In App

Scheduling priority tasks in limited time and minimizing loss

Improve
Improve
Like Article
Like
Save
Share
Report

Given n tasks with arrival time, priority and number of time units they need. We need to schedule these tasks on a single resource. The objective is to arrange tasks such that maximum priority tasks are taken. Objective is to minimize sum of product of priority and left time of tasks that are not scheduled due to limited time. This criteria simply means that the scheduling should cause minimum possible loss. Examples:

Input : Total time = 3
        Task1: arrival = 1, units = 2, priority = 300
        Task2: arrival = 2, units = 2, priority = 100
Output : 100
Explanation : Two tasks are given and time to finish 
them is 3 units. First task arrives at time 1 and it
needs 2 units. Since no other task is running at that
time, we take it. 1 unit of task 1 is over. Now task 2 
arrives. The priority of task 1 is more than task 2 
(300 > 100) thus 1 more unit  of task 1 is employed. 
Now 1 unit of time is left and we have 2 units of task
2 to be done. So simply 1 unit of task 2 is done and 
the answer is ( units of task 2 left X priority of 
task 2 ) = 1 X 100 = 100

Input : Total Time = 3
        Task1: arrival = 1, units = 1, priority = 100
        Task2: arrival = 2, units = 2, priority = 300
Output : 0

We use a priority queue and schedule one unit of task at a time.

  1. Initialize total loss as sum of each priority and units. The idea is to initialize result as maximum, then one by one subtract priorities of tasks that are scheduled.
  2. Sort all tasks according to arrival time.
  3. Process through each unit of time from 1 to total time. For current time, pick the highest priority task that is available. Schedule 1 unit of this task and subtract its priority from total loss.

Below is C++ implementation of above steps. 

CPP




// C++ code for task scheduling on basis
// of priority and arrival time
#include "bits/stdc++.h"
using namespace std;
 
// t is total time. n is number of tasks.
// arriv[] stores arrival times. units[]
// stores units of time required. prior[]
// stores priorities.
int minLoss(int n, int t, int arriv[],
   int units[], int prior[])
{
 // Calculating maximum possible answer
 // that could be calculated. Later we
 // will subtract the tasks from it
 // accordingly.
 int ans = 0;
 for (int i = 0; i < n; i++)
  ans += prior[i] * units[i];
 
 // Pushing tasks in a vector so that they
 // could be sorted according with their
 // arrival time
 vector<pair<int, int> > v;
 for (int i = 0; i < n; i++)
  v.push_back({ arriv[i], i });
 
 // Sorting tasks in vector identified by
 // index and arrival time with respect
 // to their arrival time
 sort(v.begin(), v.end());
 
 // Priority queue to hold tasks to be
 // scheduled.
 priority_queue<pair<int, int> > pq;
 
 // Consider one unit of time at a time.
 int ptr = 0; // index in sorted vector
 for (int i = 1; i <= t; i++) {
 
  // Push all tasks that have arrived at
  // this time. Note that the tasks that
  // arrived earlier and could not be scheduled
  // are already in pq.
  while (ptr < n and v[ptr].x == i) {
   pq.push({ prior[v[ptr].y], units[v[ptr].y] });
   ptr++;
  }
 
  // Remove top priority task to be scheduled
  // at time i.
  if (!pq.empty()) {
   auto tmp = pq.top();
   pq.pop();
 
   // Removing 1 unit of task
   // from answer as we could
   // schedule it.
   ans -= tmp.x;
   tmp.y--;
   if (tmp.y)
    pq.push(tmp);
  }
 }
 
 return ans;
}
 
// driver code
int main()
{
 int n = 2, t = 3;
 int arriv[] = { 1, 2 };
 int units[] = { 2, 2 };
 int prior[] = { 100, 300 };
 
 printf("%d\n", minLoss(n, t, arriv, units, prior));
 return 0;
}


Java




// Java code for task scheduling on basis
// of priority and arrival time
import java.util.*;
 
// Pair class definition
class Pair<X, Y> {
 
  // Data members
  private X key;
  private Y value;
 
  // Constructor
  public Pair(X x, Y y)
  {
    this.key = x;
    this.value = y;
  }
 
  // Getters
  public X getKey() { return key; }
 
  public Y getValue() { return value; }
 
  // Setters
  public void setKey(X x) { key = x; }
 
  public void setValue(Y y) { value = y; }
}
 
class GFG {
 
  // t is total time. n is number of tasks.
  // arriv[] stores arrival times. units[]
  // stores units of time required. prior[]
  // stores priorities.
  static int minLoss(int n, int t, int arriv[],
                     int units[], int prior[])
  {
    // Calculating maximum possible answer
    // that could be calculated. Later we
    // will subtract the tasks from it
    // accordingly.
    int ans = 0;
    for (int i = 0; i < n; i++)
      ans += prior[i] * units[i];
 
    // Pushing tasks in a ArrayList so that they
    // could be sorted according with their
    // arrival time
    ArrayList<Pair<Integer, Integer> > v
      = new ArrayList<Pair<Integer, Integer> >();
    for (int i = 0; i < n; i++)
      v.add(new Pair<Integer, Integer>(arriv[i], i));
 
    // Sorting tasks in ArrayList identified by
    // index and arrival time with respect
    // to their arrival time
    Collections.sort(
      v, new Comparator<Pair<Integer, Integer> >() {
        public int compare(
          Pair<Integer, Integer> p1,
          Pair<Integer, Integer> p2)
        {
          return p1.getKey() - p2.getKey();
        }
      });
 
    // Priority queue to hold tasks to be
    // scheduled.
    PriorityQueue<Pair<Integer, Integer> > pq
      = new PriorityQueue<Pair<Integer, Integer> >(
      new Comparator<Pair<Integer, Integer> >() {
        public int compare(
          Pair<Integer, Integer> p1,
          Pair<Integer, Integer> p2)
        {
          if (p1.getKey() != p2.getKey())
            return p2.getKey()
            - p1.getKey();
 
          return p1.getValue()
            - p2.getValue();
        }
      });
 
    // Consider one unit of time at a time.
    int ptr = 0; // index in sorted ArrayList
    for (int i = 1; i <= t; i++) {
 
      // Push all tasks that have arrived at
      // this time. Note that the tasks that
      // arrived earlier and could not be scheduled
      // are already in pq.
      while (ptr < n && v.get(ptr).getKey() == i) {
        pq.add(new Pair<Integer, Integer>(
          prior[v.get(ptr).getValue()],
          units[v.get(ptr).getValue()]));
        ptr++;
      }
 
      // Remove top priority task to be
      // scheduled at time i.
      if (!pq.isEmpty()) {
        Pair<Integer, Integer> tmp = pq.peek();
        pq.poll();
 
        // Removing 1 unit of task
        // from answer as we could
        // schedule it.
        ans -= tmp.getKey();
        tmp.setValue(tmp.getValue() - 1);
        if (tmp.getValue() > 0)
          pq.add(tmp);
      }
    }
 
    return ans;
  }
 
  // driver code
  public static void main(String[] args)
  {
    int n = 2, t = 3;
    int arriv[] = { 1, 2 };
    int units[] = { 2, 2 };
    int prior[] = { 100, 300 };
 
    System.out.println(
      minLoss(n, t, arriv, units, prior));
  }
}


Python3




# Python3 code for task scheduling on basis
# of priority and arrival time
import heapq
 
# t is total time. n is number of tasks.
# arriv[] stores arrival times. units[]
# stores units of time required. prior[]
# stores priorities.
def minLoss(n, t, arriv, units, prior):
    # Calculating maximum possible answer
    # that could be calculated. Later we
    # will subtract the tasks from it
    # accordingly.
    ans = 0
    for i in range(n):
        ans += prior[i] * units[i]
     
    # Pushing tasks in a list so that they
    # could be sorted according with their
    # arrival time
    v = []
    for i in range(n):
        v.append((arriv[i], i))
     
    # Sorting tasks in list identified by
    # index and arrival time with respect
    # to their arrival time
    v.sort()
     
    # Priority queue to hold tasks to be
    # scheduled.
    pq = []
     
    # Consider one unit of time at a time.
    ptr = 0 # index in sorted list
    for i in range(1, t+1):
     
        # Push all tasks that have arrived at
        # this time. Note that the tasks that
        # arrived earlier and could not be scheduled
        # are already in pq.
        while ptr < n and v[ptr][0] == i:
            pq.append((-prior[v[ptr][1]], units[v[ptr][1]]))
            ptr += 1
         
        pq.sort()
         
        # Remove top priority task to be
        # scheduled at time i.
        if pq:
            tmp = heapq.heappop(pq)
     
            # Removing 1 unit of task
            # from answer as we could
            # schedule it.
            ans += tmp[0]
            tmp = (tmp[0], tmp[1]-1)
            if tmp[1]:
                heapq.heappush(pq, tmp)
     
    return ans
 
# driver code
n = 2
t = 3
arriv = [1, 2]
units = [2, 2]
prior = [100, 300]
 
print(minLoss(n, t, arriv, units, prior))
 
# This code is contributed by phasing17.


C#




// C# code for task scheduling on basis
// of priority and arrival time
using System;
using System.Collections.Generic;
 
class TComparer<TKey> : IComparer<Tuple<int, int> > {
  public int Compare(Tuple<int, int> p1,
                     Tuple<int, int> p2)
  {
    if (p1.Item1 != p2.Item1)
      return p2.Item1 - p1.Item1;
 
    return p1.Item2 - p2.Item2;
  }
}
 
class GFG {
 
  // t is total time. n is number of tasks.
  // arriv[] stores arrival times. units[]
  // stores units of time required. prior[]
  // stores priorities.
  static int MinLoss(int n, int t, int[] arriv,
                     int[] units, int[] prior)
  {
    // Calculating maximum possible answer
    // that could be calculated. Later we
    // will subtract the tasks from it
    // accordingly.
    int ans = 0;
    for (int i = 0; i < n; i++)
      ans += prior[i] * units[i];
 
    // Pushing tasks in a List so that they
    // could be sorted according with their
    // arrival time
    List<Tuple<int, int> > v
      = new List<Tuple<int, int> >();
    for (int i = 0; i < n; i++)
      v.Add(new Tuple<int, int>(arriv[i], i));
 
    // Sorting tasks in List identified by
    // index and arrival time with respect
    // to their arrival time
    v.Sort((a, b) => a.Item1.CompareTo(b.Item1));
 
    // Sorted list to hold tasks to be
    // scheduled.
    SortedList<Tuple<int, int>, bool> sl
      = new SortedList<Tuple<int, int>, bool>(
      new TComparer<Tuple<int, int> >());
 
    // Consider one unit of time at a time.
    int ptr = 0; // index in sorted List
    for (int i = 1; i <= t; i++) {
 
      // Push all tasks that have arrived at
      // this time. Note that the tasks that
      // arrived earlier and could not be scheduled
      // are already in sl.
      while (ptr < n && v[ptr].Item1 == i) {
        sl.Add(new Tuple<int, int>(
          prior[v[ptr].Item2],
          units[v[ptr].Item2]),
               true);
        ptr++;
      }
 
      // Remove top priority task to be
      // scheduled at time i.
      if (sl.Count > 0) {
        Tuple<int, int> tmp = sl.Keys[0];
        sl.RemoveAt(0);
 
        // Removing 1 unit of task
        // from answer as we could
        // schedule it.
        ans -= tmp.Item1;
        tmp = Tuple.Create(tmp.Item1,
                           tmp.Item2 - 1);
        if (tmp.Item2 > 0)
          sl.Add(tmp, true);
      }
    }
 
    return ans;
  }
 
  // driver code
  public static void Main(string[] args)
  {
    int n = 2, t = 3;
    int[] arriv = { 1, 2 };
    int[] units = { 2, 2 };
    int[] prior = { 100, 300 };
 
    Console.WriteLine(
      MinLoss(n, t, arriv, units, prior));
  }
}
 
// This code is contributed by phasing17


Javascript




function MinLoss(n, t, arriv, units, prior) {
  // Calculating maximum possible answer
  // that could be calculated. Later we
  // will subtract the tasks from it
  // accordingly.
    let ans = 0;
    for (let i = 0; i < n; i++)
      ans += prior[i] * units[i];
 
  // Pushing tasks in an array so that they
  // could be sorted according with their
  // arrival time
    let v = [];
    for (let i = 0; i < n; i++)
      v.push([arriv[i], i]);
 
  // Sorting tasks in array identified by
  // index and arrival time with respect
  // to their arrival time
    v.sort((a, b) => a[0] - b[0]);
 
  // Sorted list to hold tasks to be
  // scheduled.
    let sl = [];
    let compare = (a, b) => b[0] - a[0] || a[1] - b[1]
 
  // Consider one unit of time at a time.
    let ptr = 0; // index in sorted array
    for (let i = 1; i <= t; i++) {
 
  // Push all tasks that have arrived at
  // this time. Note that the tasks that
  // arrived earlier and could not be scheduled
  // are already in sl.
      while (ptr < n && v[ptr][0] == i) {
        sl.push([prior[v[ptr][1]], units[v[ptr][1]]]);
        ptr++;
      }
 
  // Remove top priority task to be
  // scheduled at time i.
      if (sl.length > 0) {
        sl.sort(compare);
        let tmp = sl.shift();
 
  // Removing 1 unit of task
  // from answer as we could
  // schedule it.
        ans -= tmp[0];
        tmp[1] -= 1;
        if (tmp[1] > 0)
          sl.push(tmp);
      }
    }
 
    return ans;
  }
 
// driver code
  let n = 2, t = 3;
  let arriv = [ 1, 2 ];
  let units = [ 2, 2 ];
  let prior = [ 100, 300 ];
 
  console.log(MinLoss(n, t, arriv, units, prior));


Output:

100

Time Complexity: O(nlogn), used for sorting the array
Auxiliary Space: O(n), as extra space of size n, is used to make a vector of pairs.



Last Updated : 14 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads