Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

My Java application using Netbeans IDE 8.2 should track the following events which occur during each time slice and print these activies: 1. *** Cycle

My Java application using Netbeans IDE 8.2 should track the following events which occur during each time slice and print these activies:

1. *** Cycle #: c *** at the beginning of each cycle, followed by the number of processes in the ready queue of each processor in the format CPU 1 (n1) CPU 2 (n2).

2. During each cycle, your simulator will examine the status of the ready queues for each core:

(a) Whenever the ready queue for a CPU is empty, your simulator prints CPU k: idle, where k =1 or 2 is the CPU number.

(b) Whenever the ready queue for a CPU is non-empty, your simulator tracks these events:

i. If the process at the head of the CPU is not running, it begins executing the process and updates the start and wait metadata fields of its process control block (PCB). Additionally, variables that are relevant to your analysis are updated.

ii. If the process at the head of the CPU is running, the simulator checks whether the processs quantum has expired. If it has, the message CPU k: Process # x has just terminated. should be displayed. If its quantum has not expired, CPU k: Process # x is executing. The letter x denotes the PID of the process.

3. The simulator should also track process creation and scheduling during each cycle using the following policy.

(a) If no new process is created during a cycle, the message No new job this cycle. should be displayed.

(b) If one new job is created, the message One new job this cycle. should be displayed. If both ready queues have the same length, the process is scheduled on CPU 1. If the ready queues have different lengths, the process is scheduled on the CPU with the shorter ready queue. When the new process is scheduled the message CPU k: Adding job with pid # x and priority p and length t. should be displayed.

(c) If two new jobs are created, the message Two new jobs this cycle. should be displayed. If both ready queues have the same length, one process is scheduled on CPU 1 and the other on CPU2. If the ready queues have different lengths, both processes are scheduled on the CPU with the shorter ready queue. For each new process that is scheduled the message CPU k: Adding job with pid # x and priority p and length t. should be displayed.

At the end of the simulation, the program should display the average throughput (number of processes executed per cycle) and average wait time per process for each CPU as well as the overall average throughput and average wait time per process.

To run the simulation for 1000 time slices (cycles) where the probability that a new process is created during each cycle is 0.2, the program should execute with these values as command line tokens. Be sure to seed the random number generator using time of day. Do so at the beginning of the main.

Below are the source codes for HeapException.java (class), HeapAPI.java (interface), Heap.java (class), PCB.java (class) and DualCoreSimulator.java (class), which are currently a work in progress and have syntax errors. The first thing that needs to be added is DualCoreSimulator.java as a class, and the rest of the names of the source codes can be added as classes except for HeapAPI.java, which should be created as an interface. The only source codes that need modification are the DualCoreSimulator.java and Heap.java, and the rest don't need any changes. As a reminder, the code you will see below represent a work in progress, and have syntax errors in them. I will also have sample of what the output needs to look like as well below, and the help will be very appreciative. Thanks.

------------------------------------------------------------------------------------

DualCoreSimulator.java

// This is a class.

package dualcoresimulator;

// A simple non-preemptive dual-core CPU simulator.

import java.util.ArrayList;

import java.util.Iterator;

import java.util.Random;

public class DualCoreSimulator

{

SchedulingQueue queue;

int numberOfProcesses;

private static final Random rnd = new Random();

public DualCoreSimulator(SchedulingQueue queue) {

this.queue = queue;

}

public void start() {

Process process;

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

process = new Process();

process.setBurstTime(rnd.nextInt(90) + 10);

this.queue.addProcess(process);

System.out.println("Adding process");

}

}

/**

* @param args

*/

public static void main(String []args) throws HeapException

{

ArrayList oneToThousand = new ArrayList();

for (int i = 1; i < 1001; i++)

oneToThousand.add(i); //puts 1 to 1000 in the list

for (int i : oneToThousand) //prints elements using a for-each loop

System.out.printf("%d ",i); //prints elements

System.out.println();

//uses an iterator to print elements

for (Iterator it = oneToThousand.iterator(); it.hasNext();)

System.out.printf("%d ",it.next());

System.out.println();

for (int i = oneToThousand.size()-1; i >= 0; i--)

System.out.printf("%d ",oneToThousand.get(i)); //prints elements in reverse

System.out.println();

//Deletes all the elements of this array list:

while (!oneToThousand.isEmpty())

{

System.out.printf("%d is being removed.%n",oneToThousand.remove(0));

}

}

}

------------------------------------------------------------------------------------

HeapException.java

// This is a class.

package dualcoresimulator;

// This class reports Heap exceptions.

public class HeapException extends Exception

{

/**

* Creates a new instance of HeapException without detail

* message.

*/

public HeapException()

{

}

/**

* Constructs an instance of HeapException with the specified

* detail message.

*

* @param msg the detail message.

*/

public HeapException(String msg)

{

super(msg);

}

}

---------------------------------------------------------------------------

HeapAPI.java

// This is an interface

package dualcoresimulator;

// Describes the basic operations of a max heap.

public interface HeapAPI> { /** * Determine whether the Heap is empty. * @return this method returns true if the heap is empty; * otherwise, it returns false if the heap contains at least one item. */ boolean isEmpty();

/** * Inserts an item into the Heap. * @param item the value to be inserted. */ void insert(E item);

/** * An exception is generated if this method is invoked * by an empty heap. The maximum/minimum value is removed * from the heap if the heap is not empty and its effective * size is reduced by 1. * @return the maximum (in the case of a maxheap) or the * minimum (in the case of a minheap) on the heap. * @throws HeapException when the heap is empty */ E remove() throws HeapException;

/** * An exception is generated if this method is invoked * by an empty heap * @return the maximum (in the case of a maxheap) or the * minimum (in the case of a minheap) on the heap. * @throws HeapException when the heap is empty */ E peek() throws HeapException;

/** * Gives the size of this heap * @return the size of the heap; the effective size of the * heap. */ int size(); }

----------------------------------------------------------------------------------

Heap.java

// This is a class

package dualcoresimulator;

import static java.lang.Integer.compare; import java.util.*;

// This class models an array-based binary heap that implements the // HeapAPI interface. The array holds objects that implement the // parameterized Comparable interface.

public class Heap> implements HeapAPI

{

/**

* A complete tree stored in an array list representing this

* binary heap

*/

private ArrayList tree;

/**

* Constructs an empty heap

*/

public Heap()

{

tree = new ArrayList();

}

public boolean isEmpty()

{

return tree.isEmpty();

}

public void insert(E obj)

{

tree.add(obj); // Put new value at end;

tree.add(element); // Put new value at end;

int loc = tree.size()-1; // and get its location

// Swap with parent until parent not larger

while (loc > 0 && tree.get(loc).compareTo(tree.get(parent(loc))) < 0) {

swap(tree, loc, parent(loc));

loc = parent(loc);

}

}

public E remove() throws HeapException

{

assert heapSize > 0 : "Cannot remove from an empty heap";

swap(0, --heapSize); // Swap root and sifting object

if (heapSize != 0) // Not an empty heap

siftDown(0); // perform sift process

return (E)heap[heapSize]; // Return original root

}

public E peek() throws HeapException

{

if (size == 0) throw new HeapException();

HeapAPI min = heap[1];

heap[1] = heap[size--];

percolatingDown(1);

return min;

}

public int size()

{

return tree.size();

}

/**

* Swaps a parent and child elements of this heap at the specified indices

* @param place an index of the child element on this heap

* @param parent an index of the parent element on this heap

*/

private void swap(int place, int parent)

{

int temp = items[place];

items[place] = items[parent];

items[parent] = temp;

}

/**

* Rebuilds the heap to ensure that the heap property of the tree is preserved.

* @param root the root index of the subtree to be rebuilt

*/

private void reheapify(int root)

{

int left = getLeft (root);

int right = getRight (root);

boolean winleft = compare (root, left) >= 0;

boolean winright = compare (root, right) >= 0;

if (winleft && winright) return;

if (compare (left, right) > 0) {

swap (root, left);

reheapify (left);

} else {

swap (root, right);

reheapify (right);

}

}

private int getLeft(int root) {

throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.

}

private int getRight(int root) {

throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.

}

}

---------------------------------------------------------------------------------------------------

PCB.java

// This is a class.

package dualcoresimulator;

// Models a process control block.

public class PCB implements Comparable {

/** * this process ID */ private int pid; /** * the nice (priority) value of this process */ private int priority; /** * running status 0=idle 1=running */ private int running; /** * cycle during which this process was created */ private int arrived; /** * length of time this process will take to execute */ private int length; /** * cycle during which this process begins executing */ private int start; /** * how long the process waits before it begins executing */ private int wait; /** * Creates a simulated job with default values for its parameters. */ public PCB() { priority = 19; running = 0; arrived = 0; length = 0; } /** * Creates a simulated job with the specified parameters. * @param iD the process id * @param pVal the priority value * @param run the running status * @param arr the arrival time * @param len the number of cycles this process takes to execute */ public PCB(int iD, int pVal, int run, int arr, int len) { pid = iD; priority = pVal; running = run; arrived = arr; length = len; }

/** * Gives the ID of this job. * @return the process ID */ public int getPid() { return pid; } /** * Gives the priority value of this process. * @return the priority value of this process */ public int getPriority() { return priority; }

/** * Indicates whether this process is executing.. * @return the execution status of this process */ public boolean isExecuting() { return running == 1; } /** * Sets the running status of this job. */ public void execute() { running = 1; } /** * Gives the cycle during which this process was creates * @return the cycle during which this process was created. */ public int getArrival() { return arrived; } /** * Gives the number of cycles required to execute this process. * @return the number of cycles required to execute this process */ public int getLength() { return length; } /** * Gives the cycle during which this process began executing. * @return the cycle during which this process began executing */ public int getStart() { return start; }

/** * Sets the cycle during which the process begins executing. * @param startCycle the cycle during which this process begins executing. */ public void setStart(int startCycle) { start = startCycle; } /** * Gives the number of cycles this process waited before executing. * @return the number of cycles from the process creation to its execution */ public int getWait() { return wait; }

/** * Sets the wait time for this process * @param waitTime the number of cycles that this process waited */ public void setWait(int waitTime) { wait = waitTime; }

/** * Compares this simulated job with the specified simulated job. * @param another a simulated process * @return 0 when this simulated job is the same as the specified * simulated job; -1 if this job will be executed after; otherwise 1. */ public int compareTo(PCB another) { if (running > another.running) return 1; if (running < another.running) return -1; if (priority < another.priority) return 1; if (priority > another.priority) return -1; if (arrived < another.arrived) return 1; if (arrived > another.arrived) return -1; return 0; } }

--------------------------------------------------------------

This is what the output should look like when you run it.

run:

*** Cycle #: 1

CPU 1 (0) CPU 2 (0)

CPU 1: idle.

CPU 2: idle.

One new job this cycle.

CPU 1: Adding job with pid #1 and priority 19 and length 99.

*** Cycle #: 2

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 3

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 4

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 5

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 6

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 7

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 8

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 9

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 10

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 11

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 12

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 13

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 14

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

No new job this cycle.

*** Cycle #: 15

CPU 1 (1) CPU 2 (0)

CPU 1: Process #1 is executing.

CPU 2: idle.

One new job this cycle.

CPU 2: Adding job with pid #2 and priority 19 and length 59.

*** Cycle #: 16

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 17

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 18

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 19

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 20

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 21

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 22

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 23

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 24

CPU 1 (1) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 1: Adding job with pid #3 and priority 5 and length 93.

*** Cycle #: 25

CPU 1 (2) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 26

CPU 1 (2) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 27

CPU 1 (2) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 28

CPU 1 (2) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 29

CPU 1 (2) CPU 2 (1)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 2: Adding job with pid #4 and priority -19 and length 37.

*** Cycle #: 30

CPU 1 (2) CPU 2 (2)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 1: Adding job with pid #5 and priority 0 and length 45.

*** Cycle #: 31

CPU 1 (3) CPU 2 (2)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 32

CPU 1 (3) CPU 2 (2)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 33

CPU 1 (3) CPU 2 (2)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 2: Adding job with pid #6 and priority 7 and length 27.

*** Cycle #: 34

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 35

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 36

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 37

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 38

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 39

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 40

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 41

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 42

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 43

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 44

CPU 1 (3) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 1: Adding job with pid #7 and priority 3 and length 33.

*** Cycle #: 45

CPU 1 (4) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 46

CPU 1 (4) CPU 2 (3)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 2: Adding job with pid #8 and priority 16 and length 23.

*** Cycle #: 47

CPU 1 (4) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 1: Adding job with pid #9 and priority -13 and length 43.

*** Cycle #: 48

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 49

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 50

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 51

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 52

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 53

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 54

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 55

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 56

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 57

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 58

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 59

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 60

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 61

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 62

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 63

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

*** Cycle #: 64

CPU 1 (5) CPU 2 (4)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

One new job this cycle.

CPU 2: Adding job with pid #10 and priority -2 and length 53.

*** Cycle #: 65

CPU 1 (5) CPU 2 (5)

CPU 1: Process #1 is executing.

CPU 2: Process #2 is executing.

No new job this cycle.

.

.

.

.

.

.

.

*** Cycle #: 993

CPU 1 (124) CPU 2 (123)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

No new job this cycle.

*** Cycle #: 994

CPU 1 (124) CPU 2 (123)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

One new job this cycle.

CPU 2: Adding job with pid #285 and priority -10 and length 65.

*** Cycle #: 995

CPU 1 (124) CPU 2 (124)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

Two new jobs this cycle.

CPU 1: Adding job with pid #286 and priority -11 and length 80.

CPU 2: Adding job with pid #287 and priority 7 and length 66.

*** Cycle #: 996

CPU 1 (125) CPU 2 (125)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

No new job this cycle.

*** Cycle #: 997

CPU 1 (125) CPU 2 (125)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

No new job this cycle.

*** Cycle #: 998

CPU 1 (125) CPU 2 (125)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

Two new jobs this cycle.

CPU 1: Adding job with pid #288 and priority 18 and length 68.

CPU 2: Adding job with pid #289 and priority 1 and length 82.

*** Cycle #: 999

CPU 1 (126) CPU 2 (126)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

No new job this cycle.

*** Cycle #: 1000

CPU 1 (126) CPU 2 (126)

CPU 1: Process #267 is executing.

CPU 2: Process #278 is executing.

No new job this cycle.

CPU 1: average throughput is 0.017 per cycle.

CPU 1: average wait time is 103.82352941176471.

CPU 2: average throughput is 0.02 per cycle.

CPU 2: average wait time is 105.88235294117646.

overall average throughput is 0.037 per cycle.

overall average wait time is 96.35135135135135.

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

From Herds To Insights Harnessing Data Analytics For Sustainable Livestock Farming

Authors: Prof Suresh Neethirajan

1st Edition

B0CFD6K6KK, 979-8857075487

More Books

Students also viewed these Databases questions