Add LotteryScheduling algorithm (#5656)

This commit is contained in:
Hardik Pawar
2024-10-14 12:27:55 +05:30
committed by GitHub
parent 213fd5a493
commit 0020ab2a9a
4 changed files with 214 additions and 0 deletions

View File

@ -0,0 +1,141 @@
package com.thealgorithms.scheduling;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* The LotteryScheduling class implements the Lottery Scheduling algorithm, which is
* a probabilistic CPU scheduling algorithm. Processes are assigned tickets, and
* the CPU is allocated to a randomly selected process based on ticket count.
* Processes with more tickets have a higher chance of being selected.
*/
public final class LotteryScheduling {
private LotteryScheduling() {
}
private List<Process> processes;
private Random random;
/**
* Constructs a LotteryScheduling object with the provided list of processes.
*
* @param processes List of processes to be scheduled using Lottery Scheduling.
*/
public LotteryScheduling(final List<Process> processes) {
this.processes = processes;
this.random = new Random();
}
/**
* Constructs a LotteryScheduling object with the provided list of processes and a Random object.
*
* @param processes List of processes to be scheduled using Lottery Scheduling.
* @param random Random object used for generating random numbers.
*/
public LotteryScheduling(final List<Process> processes, Random random) {
this.processes = processes;
this.random = random;
}
/**
* Schedules the processes using the Lottery Scheduling algorithm.
* Each process is assigned a certain number of tickets, and the algorithm randomly
* selects a process to execute based on ticket count. The method calculates the
* waiting time and turnaround time for each process and simulates their execution.
*/
public List<Process> scheduleProcesses() {
int totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
int currentTime = 0;
List<Process> executedProcesses = new ArrayList<>();
while (!processes.isEmpty()) {
int winningTicket = random.nextInt(totalTickets) + 1;
Process selectedProcess = selectProcessByTicket(winningTicket);
if (selectedProcess == null) {
// This should not happen in normal circumstances, but we'll handle it just in case
System.err.println("Error: No process selected. Recalculating total tickets.");
totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
continue;
}
selectedProcess.setWaitingTime(currentTime);
currentTime += selectedProcess.getBurstTime();
selectedProcess.setTurnAroundTime(selectedProcess.getWaitingTime() + selectedProcess.getBurstTime());
executedProcesses.add(selectedProcess);
processes.remove(selectedProcess);
totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
}
return executedProcesses;
}
/**
* Selects a process based on a winning ticket. The method iterates over the
* list of processes, and as the ticket sum accumulates, it checks if the
* current process holds the winning ticket.
*
* @param winningTicket The randomly generated ticket number that determines the selected process.
* @return The process associated with the winning ticket.
*/
private Process selectProcessByTicket(int winningTicket) {
int ticketSum = 0;
for (Process process : processes) {
ticketSum += process.getTickets();
if (ticketSum >= winningTicket) {
return process;
}
}
return null;
}
/**
* The Process class represents a process in the scheduling system. Each process has
* an ID, burst time (CPU time required for execution), number of tickets (used in
* lottery selection), waiting time, and turnaround time.
*/
public static class Process {
private String processId;
private int burstTime;
private int tickets;
private int waitingTime;
private int turnAroundTime;
public Process(String processId, int burstTime, int tickets) {
this.processId = processId;
this.burstTime = burstTime;
this.tickets = tickets;
}
public String getProcessId() {
return processId;
}
public int getBurstTime() {
return burstTime;
}
public int getTickets() {
return tickets;
}
public int getWaitingTime() {
return waitingTime;
}
public void setWaitingTime(int waitingTime) {
this.waitingTime = waitingTime;
}
public int getTurnAroundTime() {
return turnAroundTime;
}
public void setTurnAroundTime(int turnAroundTime) {
this.turnAroundTime = turnAroundTime;
}
}
}

View File

@ -0,0 +1,64 @@
package com.thealgorithms.scheduling;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class LotterySchedulingTest {
private Random mockRandom;
@BeforeEach
public void setup() {
mockRandom = mock(Random.class);
}
@Test
public void testLotterySchedulingWithMockedRandom() {
List<LotteryScheduling.Process> processes = createProcesses();
LotteryScheduling lotteryScheduling = new LotteryScheduling(processes, mockRandom);
// Mock the sequence of random numbers (winning tickets)
// This sequence ensures that P1 (10 tickets), P3 (8 tickets), and P2 (5 tickets) are selected.
when(mockRandom.nextInt(23)).thenReturn(5, 18, 11); // winning tickets for P1, P3, and P2
List<LotteryScheduling.Process> executedProcesses = lotteryScheduling.scheduleProcesses();
assertEquals(3, executedProcesses.size());
// Assert the process execution order and properties
LotteryScheduling.Process process1 = executedProcesses.get(0);
assertEquals("P1", process1.getProcessId());
assertEquals(0, process1.getWaitingTime());
assertEquals(10, process1.getTurnAroundTime());
LotteryScheduling.Process process2 = executedProcesses.get(1);
assertEquals("P2", process2.getProcessId());
assertEquals(10, process2.getWaitingTime());
assertEquals(15, process2.getTurnAroundTime());
LotteryScheduling.Process process3 = executedProcesses.get(2);
assertEquals("P3", process3.getProcessId());
assertEquals(15, process3.getWaitingTime());
assertEquals(23, process3.getTurnAroundTime());
}
private List<LotteryScheduling.Process> createProcesses() {
LotteryScheduling.Process process1 = new LotteryScheduling.Process("P1", 10, 10); // 10 tickets
LotteryScheduling.Process process2 = new LotteryScheduling.Process("P2", 5, 5); // 5 tickets
LotteryScheduling.Process process3 = new LotteryScheduling.Process("P3", 8, 8); // 8 tickets
List<LotteryScheduling.Process> processes = new ArrayList<>();
processes.add(process1);
processes.add(process2);
processes.add(process3);
return processes;
}
}