mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-08 10:15:51 +08:00
Add HighestResponseRatioNextScheduling.java
new algorithm with tests (#5607)
* Add `HighestResponseRatioNextScheduling.java` new algorithm with tests * Update directory * Improve class documentation * Update directory * Fix * Fix * Fix * Add suggested changes * Fix clang errors --------- Co-authored-by: Hardvan <Hardvan@users.noreply.github.com> Co-authored-by: Alex Klymenko <alexanderklmn@gmail.com>
This commit is contained in:
@ -459,6 +459,7 @@
|
|||||||
* [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java)
|
* [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java)
|
||||||
* scheduling
|
* scheduling
|
||||||
* [FCFSScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
|
* [FCFSScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
|
||||||
|
* [HighestResponseRatioNextScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/HighestResponseRatioNextScheduling.java)
|
||||||
* [MLFQScheduler](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/MLFQScheduler.java)
|
* [MLFQScheduler](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/MLFQScheduler.java)
|
||||||
* [PreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
|
* [PreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
|
||||||
* [RRScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/RRScheduling.java)
|
* [RRScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/RRScheduling.java)
|
||||||
@ -916,6 +917,7 @@
|
|||||||
* [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java)
|
* [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java)
|
||||||
* scheduling
|
* scheduling
|
||||||
* [FCFSSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
|
* [FCFSSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
|
||||||
|
* [HighestResponseRatioNextSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/HighestResponseRatioNextSchedulingTest.java)
|
||||||
* [MLFQSchedulerTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/MLFQSchedulerTest.java)
|
* [MLFQSchedulerTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/MLFQSchedulerTest.java)
|
||||||
* [PreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)
|
* [PreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)
|
||||||
* [RRSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/RRSchedulingTest.java)
|
* [RRSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/RRSchedulingTest.java)
|
||||||
|
@ -0,0 +1,158 @@
|
|||||||
|
package com.thealgorithms.scheduling;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code HighestResponseRatioNextScheduling} class implements the
|
||||||
|
* Highest Response Ratio Next (HRRN) scheduling algorithm.
|
||||||
|
* HRRN is a non-preemptive scheduling algorithm that selects the process with
|
||||||
|
* the highest response ratio for execution.
|
||||||
|
* The response ratio is calculated as:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Response Ratio = (waiting time + burst time) / burst time
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* HRRN is designed to reduce the average waiting time and improve overall
|
||||||
|
* system performance by balancing between short and long processes,
|
||||||
|
* minimizing process starvation.
|
||||||
|
*/
|
||||||
|
public final class HighestResponseRatioNextScheduling {
|
||||||
|
|
||||||
|
private static final int PROCESS_NOT_FOUND = -1;
|
||||||
|
private static final double INITIAL_MAX_RESPONSE_RATIO = -1.0;
|
||||||
|
|
||||||
|
private HighestResponseRatioNextScheduling() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a process in the scheduling algorithm.
|
||||||
|
*/
|
||||||
|
private static class Process {
|
||||||
|
String name;
|
||||||
|
int arrivalTime;
|
||||||
|
int burstTime;
|
||||||
|
int turnAroundTime;
|
||||||
|
boolean finished;
|
||||||
|
|
||||||
|
Process(String name, int arrivalTime, int burstTime) {
|
||||||
|
this.name = name;
|
||||||
|
this.arrivalTime = arrivalTime;
|
||||||
|
this.burstTime = burstTime;
|
||||||
|
this.turnAroundTime = 0;
|
||||||
|
this.finished = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the response ratio for this process.
|
||||||
|
*
|
||||||
|
* @param currentTime The current time in the scheduling process.
|
||||||
|
* @return The response ratio for this process.
|
||||||
|
*/
|
||||||
|
double calculateResponseRatio(int currentTime) {
|
||||||
|
return (double) (burstTime + currentTime - arrivalTime) / burstTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the Turn Around Time (TAT) for each process.
|
||||||
|
*
|
||||||
|
* <p>Turn Around Time is calculated as the total time a process spends
|
||||||
|
* in the system from arrival to completion. It is the sum of the burst time
|
||||||
|
* and the waiting time.</p>
|
||||||
|
*
|
||||||
|
* @param processNames Array of process names.
|
||||||
|
* @param arrivalTimes Array of arrival times corresponding to each process.
|
||||||
|
* @param burstTimes Array of burst times for each process.
|
||||||
|
* @param noOfProcesses The number of processes.
|
||||||
|
* @return An array of Turn Around Times for each process.
|
||||||
|
*/
|
||||||
|
public static int[] calculateTurnAroundTime(final String[] processNames, final int[] arrivalTimes, final int[] burstTimes, final int noOfProcesses) {
|
||||||
|
int currentTime = 0;
|
||||||
|
int[] turnAroundTime = new int[noOfProcesses];
|
||||||
|
Process[] processes = new Process[noOfProcesses];
|
||||||
|
|
||||||
|
for (int i = 0; i < noOfProcesses; i++) {
|
||||||
|
processes[i] = new Process(processNames[i], arrivalTimes[i], burstTimes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(processes, Comparator.comparingInt(p -> p.arrivalTime));
|
||||||
|
|
||||||
|
int finishedProcessCount = 0;
|
||||||
|
while (finishedProcessCount < noOfProcesses) {
|
||||||
|
int nextProcessIndex = findNextProcess(processes, currentTime);
|
||||||
|
if (nextProcessIndex == PROCESS_NOT_FOUND) {
|
||||||
|
currentTime++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process currentProcess = processes[nextProcessIndex];
|
||||||
|
currentTime = Math.max(currentTime, currentProcess.arrivalTime);
|
||||||
|
currentProcess.turnAroundTime = currentTime + currentProcess.burstTime - currentProcess.arrivalTime;
|
||||||
|
currentTime += currentProcess.burstTime;
|
||||||
|
currentProcess.finished = true;
|
||||||
|
finishedProcessCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < noOfProcesses; i++) {
|
||||||
|
turnAroundTime[i] = processes[i].turnAroundTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return turnAroundTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the Waiting Time (WT) for each process.
|
||||||
|
*
|
||||||
|
* @param turnAroundTime The Turn Around Times for each process.
|
||||||
|
* @param burstTimes The burst times for each process.
|
||||||
|
* @return An array of Waiting Times for each process.
|
||||||
|
*/
|
||||||
|
public static int[] calculateWaitingTime(int[] turnAroundTime, int[] burstTimes) {
|
||||||
|
int[] waitingTime = new int[turnAroundTime.length];
|
||||||
|
for (int i = 0; i < turnAroundTime.length; i++) {
|
||||||
|
waitingTime[i] = turnAroundTime[i] - burstTimes[i];
|
||||||
|
}
|
||||||
|
return waitingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the next process to be scheduled based on arrival times and the current time.
|
||||||
|
*
|
||||||
|
* @param processes Array of Process objects.
|
||||||
|
* @param currentTime The current time in the scheduling process.
|
||||||
|
* @return The index of the next process to be scheduled, or PROCESS_NOT_FOUND if no process is ready.
|
||||||
|
*/
|
||||||
|
private static int findNextProcess(Process[] processes, int currentTime) {
|
||||||
|
return findHighestResponseRatio(processes, currentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the process with the highest response ratio.
|
||||||
|
*
|
||||||
|
* <p>The response ratio is calculated as:
|
||||||
|
* (waiting time + burst time) / burst time
|
||||||
|
* where waiting time = current time - arrival time</p>
|
||||||
|
*
|
||||||
|
* @param processes Array of Process objects.
|
||||||
|
* @param currentTime The current time in the scheduling process.
|
||||||
|
* @return The index of the process with the highest response ratio, or PROCESS_NOT_FOUND if no process is ready.
|
||||||
|
*/
|
||||||
|
private static int findHighestResponseRatio(Process[] processes, int currentTime) {
|
||||||
|
double maxResponseRatio = INITIAL_MAX_RESPONSE_RATIO;
|
||||||
|
int maxIndex = PROCESS_NOT_FOUND;
|
||||||
|
|
||||||
|
for (int i = 0; i < processes.length; i++) {
|
||||||
|
Process process = processes[i];
|
||||||
|
if (!process.finished && process.arrivalTime <= currentTime) {
|
||||||
|
double responseRatio = process.calculateResponseRatio(currentTime);
|
||||||
|
if (responseRatio > maxResponseRatio) {
|
||||||
|
maxResponseRatio = responseRatio;
|
||||||
|
maxIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxIndex;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package com.thealgorithms.scheduling;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class HighestResponseRatioNextSchedulingTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalculateTurnAroundTime() {
|
||||||
|
String[] processNames = {"A", "B", "C"};
|
||||||
|
int[] arrivalTimes = {0, 2, 4};
|
||||||
|
int[] burstTimes = {3, 1, 2};
|
||||||
|
int noOfProcesses = 3;
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {3, 2, 2};
|
||||||
|
int[] actualTurnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, noOfProcesses);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, actualTurnAroundTimes, "Turn Around Times do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalculateWaitingTime() {
|
||||||
|
int[] turnAroundTimes = {3, 1, 5};
|
||||||
|
int[] burstTimes = {3, 1, 2};
|
||||||
|
|
||||||
|
int[] expectedWaitingTimes = {0, 0, 3};
|
||||||
|
int[] actualWaitingTimes = HighestResponseRatioNextScheduling.calculateWaitingTime(turnAroundTimes, burstTimes);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedWaitingTimes, actualWaitingTimes, "Waiting Times do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompleteSchedulingScenario() {
|
||||||
|
String[] processNames = {"A", "B", "C"};
|
||||||
|
int[] arrivalTimes = {0, 1, 2};
|
||||||
|
int[] burstTimes = {5, 2, 1};
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {5, 7, 4};
|
||||||
|
int[] turnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, processNames.length);
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, turnAroundTimes, "Turn Around Times do not match");
|
||||||
|
|
||||||
|
int[] expectedWaitingTimes = {0, 5, 3};
|
||||||
|
int[] waitingTimes = HighestResponseRatioNextScheduling.calculateWaitingTime(turnAroundTimes, burstTimes);
|
||||||
|
assertArrayEquals(expectedWaitingTimes, waitingTimes, "Waiting Times do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testZeroProcesses() {
|
||||||
|
String[] processNames = {};
|
||||||
|
int[] arrivalTimes = {};
|
||||||
|
int[] burstTimes = {};
|
||||||
|
int noOfProcesses = 0;
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {};
|
||||||
|
int[] actualTurnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, noOfProcesses);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, actualTurnAroundTimes, "Turn Around Times for zero processes should be an empty array");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllProcessesArriveAtSameTime() {
|
||||||
|
String[] processNames = {"A", "B", "C", "D"};
|
||||||
|
int[] arrivalTimes = {0, 0, 0, 0};
|
||||||
|
int[] burstTimes = {4, 3, 1, 2};
|
||||||
|
int noOfProcesses = 4;
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {4, 10, 5, 7};
|
||||||
|
int[] actualTurnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, noOfProcesses);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, actualTurnAroundTimes, "Turn Around Times for processes arriving at the same time do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessesWithZeroBurstTime() {
|
||||||
|
String[] processNames = {"A", "B", "C"};
|
||||||
|
int[] arrivalTimes = {0, 1, 2};
|
||||||
|
int[] burstTimes = {3, 0, 2};
|
||||||
|
int noOfProcesses = 3;
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {3, 2, 3};
|
||||||
|
int[] actualTurnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, noOfProcesses);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, actualTurnAroundTimes, "Turn Around Times for processes with zero burst time do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessesWithLargeGapsBetweenArrivals() {
|
||||||
|
String[] processNames = {"A", "B", "C"};
|
||||||
|
int[] arrivalTimes = {0, 100, 200};
|
||||||
|
int[] burstTimes = {10, 10, 10};
|
||||||
|
int noOfProcesses = 3;
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {10, 10, 10};
|
||||||
|
int[] actualTurnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, noOfProcesses);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, actualTurnAroundTimes, "Turn Around Times for processes with large gaps between arrivals do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessesWithVeryLargeBurstTimes() {
|
||||||
|
String[] processNames = {"A", "B"};
|
||||||
|
int[] arrivalTimes = {0, 1};
|
||||||
|
int[] burstTimes = {Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2};
|
||||||
|
int noOfProcesses = 2;
|
||||||
|
|
||||||
|
int[] expectedTurnAroundTimes = {Integer.MAX_VALUE / 2, Integer.MAX_VALUE - 2};
|
||||||
|
int[] actualTurnAroundTimes = HighestResponseRatioNextScheduling.calculateTurnAroundTime(processNames, arrivalTimes, burstTimes, noOfProcesses);
|
||||||
|
|
||||||
|
assertArrayEquals(expectedTurnAroundTimes, actualTurnAroundTimes, "Turn Around Times for processes with very large burst times do not match");
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user