Skip to content

Add LotteryScheduling new algorithm with Junit tests #5656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 14, 2024
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@
* [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)
* [JobSchedulingWithDeadline](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/JobSchedulingWithDeadline.java)
* [LotteryScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/LotteryScheduling.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)
* [RRScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/RRScheduling.java)
Expand Down Expand Up @@ -1019,6 +1020,7 @@
* [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)
* [JobSchedulingWithDeadlineTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/JobSchedulingWithDeadlineTest.java)
* [LotterySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/LotterySchedulingTest.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)
* [RRSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/RRSchedulingTest.java)
Expand Down
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.14.1</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
134 changes: 134 additions & 0 deletions src/main/java/com/thealgorithms/scheduling/LotteryScheduling.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
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);

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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Loading