Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

A current area of research involves modelling propagation on a network. For exam

ID: 3707510 • Letter: A

Question

A current area of research involves modelling propagation on a network. For example, we can use the model to study how disease spreads in a society or how fast information spreads across a social netwvork. Your project should contain the following classes 1. The Entity class. The entity represents a person, organization, or other entity in the social network. The Entity class contains an enum type that indicates the health Infected, Inoculated, BeingInfected, BeingInoculated. (See below for a status of the entity. The enum should be called Health have the values Uninfected, description of the enum type.) The Entity class should implement the Comparable interface, and entities can be ordered by their name. The Entity class contains the following methods 1. getName and setName: the name is a String 2. getHealthStatus and setHealthstatus: the health status is the enum Health type 3. getRelations: relations is a linked list that stores Entity objects 4. equals: the equals method overrides the one in object. Two Entity objects are equal if they have the same name. 5. toString: the string representation should be the name and health status of the entity The entity class constructor should take the entity's name as input and set the name, initialize the relations to an empty linked list, and initialize the health status to Uninfected 2. The Network class. The network represents the social network of entities. The Network class should implement the Iterable interface and should contain a linked list that stores all the entities of the network. The Iterator for the network should iterate over all the entities in the network. The Network class contains the following methods 1. addRelation takes two Entity objects. If either entity is not in the network, it is added to the network. (There should not be duplicate entities in the network.) Then, for each entity, add the other entity to its relations list. 2. removeRelation takes two Entity objects. Each entity is removed from the other's relations list. The entities are not removed from the network. 3. addRelations takes a File parameter. The file contains a list of relations. Each relation will be a pair of names. The names of a relation pair are separated by a comma, and each relation pair is on its own line. For example University Hospitals, Cleveland Clinc University Hosptials, Louis Stokes Cleveland VA Medical Center Cleveland Clinic, Mercy Regional Medical Center The method may throw an exception if there is a problem with the file. Each pair of names should be added to the network as a relation of Entity objects with those names. 4. addRelations takes a variable length parameter of Strings. There should be an even number of strings. An exception may be thrown if there is not an even number. The method should create Entity instances for each String and for each pair of names (first two names, second two names, etc.) the pair of entities should be added to the network as a relation The Network class should have a constructor that takes no input and initializes an empty network.

Explanation / Answer

PropagationStudy.java


import java.util.Random;
import java.io.*;

public class PropagationStudy{
    /**The Network object used by this study.*/
    private Network _Network;
    /**The rate of infection, on range [0,1]*/
    private double _InfectionRate;
    /**The rate of healing, on range [0,1]*/
    private double _HealRate;
    /**The rate of wear, on the range [0,1]*/
    private double _WearRate;
    /**The High Random Number God (or Generator)*/
    private Random _HighRNG;

    /**The constructor*/
    public PropagationStudy(Network net, double rateInfect, double rateHeal,
                double rateWear){
   setNetwork(net);
   setInfectionRate(rateInfect);
   setHealRate(rateHeal);
   setWearRate(rateWear);
   _HighRNG = new Random();
    }

    public void infect(Entity victim) throws NoSuchElementException{
   Entity condemned = ((LinkedListIterator<Entity>) getNetwork().iterator()
                ).find(victim); //ptr to Entity to be sickened
   if(condemned != null){
        condemned.setHealthStatus(Health.Infected);
   }
   else{
        throw new NoSuchElementException();
   }
    }

    public void infect(double chance){
   //walk the network
   for(Entity each : getNetwork()){
        //if each rolls too low (below chance), ends up sick.
        if(each.getHealthStatus() != Health.Infected
           && _HighRNG.nextDouble() < chance){
       each.setHealthStatus(Health.Infected);
        }
   }
    }

    public void inoculate(Entity victim) throws NoSuchElementException{
   Entity condemned = ((LinkedListIterator<Entity>) getNetwork().iterator()
                ).find(victim);//Entity to be inoculated
   if(condemned != null){
        condemned.setHealthStatus(Health.Inoculated);
   }
   else{
        throw new NoSuchElementException();
   }
    }
    public void inoculate(double chance){
   //walk the network
   for(Entity each : getNetwork()){
        //if each rolls too low (below chance), ends up sick.
        if(each.getHealthStatus() != Health.Inoculated
           && _HighRNG.nextDouble() < chance){
       each.setHealthStatus(Health.Inoculated);
        }
   }
    }
    public int getNumUninfected(){
   int count = 0; //how many so far
   //walk the network
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.Uninfected){
       count++;
        }
   }
   return count;
    }
    public int getNumInoculated(){
   int count = 0; //how many so far
   //walk the network
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.Inoculated){
       count++;
        }
   }
   return count;
    }
    public int getNumInfected(){
   int count = 0; //how many so far
   //walk the network
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.Infected){
       count++;
        }
   }
   return count;
    }
    public void resetNetwork(){
   //walk the network
   for(Entity each : getNetwork()){
        each.setHealthStatus(Health.Uninfected);
   }
    }

    public void printNetwork(){
   ( (LinkedListIterator<Entity>) getNetwork().iterator() ).mergeSort();
   //loop over the new list, printing as needed
   for(Entity each : getNetwork()){
        System.out.println(each.getName() + ": " + //better with printf
                   each.getHealthStatus());
   }
    }
    public void runPropagation(){
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.Infected){
       //walk each sick Entity's relations
       for(Entity eachRel : each.getRelations()){
            if(eachRel.getHealthStatus() == Health.Uninfected){
           if(_HighRNG.nextDouble() < getInfectionRate()){
                eachRel.setHealthStatus(Health.BeingInfected);
           }
            }
       }
        }
   }
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.Infected){
       if(_HighRNG.nextDouble() < getHealRate()){
            each.setHealthStatus(Health.BeingInoculated);
       }
        }
   }
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.Inoculated){
       if(_HighRNG.nextDouble() < getWearRate()){
            each.setHealthStatus(Health.Uninfected);
       }
        }
   }
   for(Entity each : getNetwork()){
        if(each.getHealthStatus() == Health.BeingInfected){
       each.setHealthStatus(Health.Infected);
        }
        else if(each.getHealthStatus() == Health.BeingInoculated){
       each.setHealthStatus(Health.Inoculated);
        }
   }
    }
    public void runPropagation(int rounds){
   //Call runPropagation() until it is zero; rounds-many times.
   while(rounds-- > 0){
        runPropagation();
   }
    }
    public Network getNetwork(){
   return _Network;
    }
  
    public void setNetwork(Network value){
   _Network = value;
    }
    public double getInfectionRate(){
   return _InfectionRate;
    }
    public void setInfectionRate(double value){
   _InfectionRate = value;
    }
    public double getHealRate(){
   return _HealRate;
    }
    public void setHealRate(double value){
   _HealRate = value;
    }
    public double getWearRate(){
   return _WearRate;
    }
    public void setWearRate(double value){
   _WearRate = value;
    }
    public static void main(String[] args){
   PropagationStudy study; //assign ptr later
   //begin setting up
   try{// Need this to catch IO exceptions
        /*make a Network*/
        Network net = new Network();
        net.addRelations(new File(args[0]));
        /*make a new study*/
        study = new PropagationStudy(net, Double.parseDouble(args[1]),
                   Double.parseDouble(args[2]),
                   Double.parseDouble(args[3])   );
        BufferedReader river = new BufferedReader(new FileReader(args[5]));
        String line = river.readLine(); //each line of the file
        //loop over the input and build the names
        while(line != null){            //a do-while could clean this
       //make an ideal Entity, for which to search
       Entity missing = new Entity(line);
       //create an iterator, for use in searching
       LinkedListIterator<Entity> iterator =
            (LinkedListIterator<Entity>)
            study.getNetwork().iterator();
       //find the Entity and stash the ptr here
       Entity found = iterator.find(missing);

       if(found != null){
            found.setHealthStatus(Health.Infected);
       }
       else{
            System.out.printf("%s is not in the network. ", line);
       }
       line = river.readLine(); //auto-advance
        }
        river.close();
        if(args.length == 7){ //because last file is optional
       river = new BufferedReader(new FileReader(args[5]));
       line = river.readLine(); //each line of the file
       //loop over the input and build the names
       while(line != null){
            //make an ideal Entity, for which to search
            Entity missing = new Entity(line);
            //create an iterator, for use in searching
            LinkedListIterator<Entity> iterator =
           (LinkedListIterator<Entity>)
           study.getNetwork().iterator();
            //find the Entity and stash the ptr here
            Entity found = iterator.find(missing);

            if(found != null){
           found.setHealthStatus(Health.Inoculated);
            }
            else{
           System.out.printf("%s is not in the network. ",
                      line);
            }
            line = river.readLine(); //auto-advance
       }
       river.close();
        }
   }
   catch(IOException e){
        System.out.printf("File IO error, program aborted " );
        return;
   }
   study.runPropagation(Integer.parseInt(args[4]));
   /*now spit out the number of each type*/
   System.out.printf("Quantity uninfected: %d ",study.getNumUninfected());
   System.out.printf("Quantity infected: %d ", study.getNumInfected());
   System.out.printf("Quantity inoculated: %d ",study.getNumInoculated());
    }
}


Health.java
public enum Health{
    Uninfected, Infected, Inoculated, BeingInfected, BeingInoculated;
}

Entity.java


import java.lang.Comparable;
public class Entity implements Comparable<Entity>{
    /**Name of this Entity.*/
    private String _Name;
    /**Status of the Entity, as a Health enum.*/
    private Health _HealthStatus;
    /**Other Entity-s to which this Entity is linked.*/
    private LinkedList<Entity> _Relations;

    public Entity(String name){
   setName(name);
   _Relations = new LinkedList<Entity>();
   setHealthStatus(Health.Uninfected);
    }
    @Override
    public int compareTo(Entity o){
   //these two local vars should be self-explanatory
   String me   = this.getName();
   String you = o.getName();
   boolean same = true;     //for the loop
   int     out = 0;        //need to return 1, 0, or -1.
   for(int i = 0; same && i < ( ((me.length() - you.length() ) > 0) ?
                     you.length() : me.length() ); i++){
        if( (me.charAt(i)&0x1F) != (you.charAt(i)&0x1F) ){
       //only 5-least-significant-bits matter (b/c case independant)
       same = false;//save processing; they are no longer the same
       if( me.charAt(i) > you.charAt(i) ){
            out = 1;
       }
       else{
            out = -1;
       }
        }
   }
   //if names were identical, out should still be zero. Else, is +/- 1.
   return out;
    }
    @Override
    public boolean equals(Object obj){
   Entity otherOne = (Entity) obj; //This is the proper type.
   //using String.equals(), not this.equals()
   return this.getName().equals(otherOne.getName());
    }
    public String toString(){
   return this.getName() + ": " + this.getHealthStatus();
    }
    public LinkedList<Entity> getRelations(){
   return _Relations;
    }
    public String getName(){
   return _Name;
    }
    public void setName(String value){
   _Name = value;
    }
    public Health getHealthStatus(){
   return _HealthStatus;
    }
    public void setHealthStatus(Health value){
   _HealthStatus = value;
    }
}

Network.java

import java.lang.Iterable;
import java.util.Iterator;
import java.io.*;
public class Network implements Iterable<Entity>{
    /**The DB for the Network. Get/set is verboten.*/
    private LinkedList<Entity> _Data;

    /**Creates a new, empty Network.*/
    public Network(){
   _Data = new LinkedList<Entity>();
    }
    @Override
    public Iterator<Entity> iterator(){
   return new LinkedListIterator<Entity>(_Data);
    }
    public void addRelation(Entity one, Entity two){
   boolean>    boolean twoNeeded = true;
   //first, walk the net and check for duplicates
   for(Entity each : _Data){
        if(oneNeeded && each.equals(one)){
      >        //one now points to the entry in _Data
        }
        if(twoNeeded && each.equals(two)){
       twoNeeded = false;
       two = each; //two now points to the entry in _Data
        }
        if(!(oneNeeded || twoNeeded)){ // NOR
       //No need to loop further
       one.getRelations().addToBack(two);
       two.getRelations().addToBack(one);
       return; //like break, but not verboten.
        }
   }
   //At least one is not in _Data
   if(oneNeeded){
        _Data.addToBack(one);
   }
   if(twoNeeded){
        _Data.addToBack(two);
   }
   //now, connect them
   one.getRelations().addToBack(two);
   two.getRelations().addToBack(one);
    }
    public void removeRelation(Entity one, Entity two){
   //search the relations of one for a match for two
   LinkedListIterator<Entity> itOne =
        (LinkedListIterator<Entity>) one.getRelations().iterator();
   itOne.find(two);
   itOne.remove();
   //search the relations of two for a match for one
   LinkedListIterator<Entity> itTwo =
        (LinkedListIterator<Entity>) two.getRelations().iterator();
   itTwo.find(one);
   itTwo.remove();
    }
    public void addRelations(File batch){
   try{//because File IO problems
        //river is for reading the file of Infected Entitys
        BufferedReader river = new BufferedReader(new FileReader(batch));
        String line = river.readLine(); //each line of the file
        //loop over the input and build the names
        while(line != null){            //a do-while could clean this up
       boolean alive = true;       //to end the for loop early
       //find the comma, addRelation the names
       for(int i = 0; alive && i < line.length(); i++){
            if(line.charAt(i) == ','){
           addRelation(new Entity(line.substring(0, i)),
                    new Entity(line.substring(i+2)) );
           alive = false;
            }
       }
       line = river.readLine();
        }
        river.close();
   }
   catch(IOException e){/*stifle*/}
    }
    public void addRelations(String... in) throws IllegalArgumentException{
   if((in.length & 1) == 0){ //if even qty
        //adds each pair of Strings
        for(int i = 0; i < in.length; i++){
       addRelation(new Entity(in[i++]), new Entity(in[i]));
        }
   }
   else{
        throw new IllegalArgumentException();
   }
    }
}

LinkedList.java

import java.lang.Iterable;
import java.util.Iterator;
public class LinkedList<T extends Comparable<? super T>> implements Iterable<T>{
    /**Front of the list. */
    private Node<T> _Front;
    /**Other end of the List*/
    private Node<T> _Back;

    /**Make a new, empty list.*/
    public LinkedList(){
   setFront(null);
   setBack(null);
    }
    public void addToFront(T element){
   Node<T> newbie = new Node<T>(element, getFront(), null);//new entry
   setFront(newbie);
   if(getBack() == null){ //if this is first entry
        setBack(newbie);
   }
   else{ //not the first entry
        newbie.getNext().setPrev(newbie);
   }
    }
    public void addToBack(T element){
   Node<T> newbie = new Node<T>(element, null, getBack());
   setBack(newbie);
   if(getFront() == null){ //first!
        setFront(newbie);
   }
   else{ //not the first entry
        newbie.getPrev().setNext(newbie);
   }
    }
    public T removeFromFront() throws java.util.NoSuchElementException{
   Node<T> out = getFront();   //save the ptr
   if(out == null){ //if empty list
        throw new java.util.NoSuchElementException();
   }
   if(getFront() != getBack()){//if more than one node
        out.getNext().setPrev(null);//break the other
        setFront(out.getNext());    //correct the head
        out.setNext(null);          //break one link
   }
   else{ //one node --> no nodes
        setFront(null);
        setBack(null);
   }
   return out.getElement();      
    }
    public T removeFromBack() throws java.util.NoSuchElementException{
   Node<T> out = getBack();    //save
   if(out == null){
        throw new java.util.NoSuchElementException();
   }
   if(getFront() != getBack()){//if more than one node
        out.getPrev().setNext(null);//break the other
        setBack(out.getPrev());     //correct the head
        out.setPrev(null);    //break one link
   }
   else{
        setFront(null);
        setBack(null);
   }
   return out.getElement();
    }
    public boolean isEmpty() {
   return (getFront() == null); //if front null, back should be too
    }
    public void sort(){
   setFront(mergeSortNodes(getFront()));
   //re-link
   Node<T> buffer = getFront(); //stores last node
   while(buffer.getNext() != null){
        buffer.getNext().setPrev(buffer);
        buffer = buffer.getNext();
   }
    }
    private Node<T> mergeSortNodes(Node<T> given){
   // if only 1 node, then the list is already sorted
   if (given.getNext() == null)
        return given;
  
   // 1. split the list into 2
   Node<T> half = split(given);
   given = mergeSortNodes(given); //cut in half
   half = mergeSortNodes(half);
  
   // 3. merge the two sorted halves together
   return merge(given, half);
    }
    private Node<T> split(Node<T> given){
   Node<T> list2 = given.getNext(); // the first removed node
   Node<T> nodeptr = list2;          // the current node in list
   Node<T> prevptr = given;          // the previous node in list
   while (nodeptr != null) {
        prevptr.setNext(nodeptr.getNext());
        prevptr = nodeptr;
        nodeptr = nodeptr.getNext();
   }
   return list2;
    }
    private Node<T> merge(Node<T> list1, Node<T> list2) {
   Node<T> result;    // the first node of the returned list
   Node<T> nodeptr;   // the last node of the returned list
  
   // first determine which is the first node of the returned list
   if (list1.getElement().compareTo(list2.getElement()) < 0) {
        result = list1;
        list1 = list1.getNext();
   }
   else {
        result = list2;
        list2 = list2.getNext();
   }
   nodeptr = result;
   while (list1 != null && list2 != null) {
        if (list1.getElement().compareTo(list2.getElement()) < 0) {
       nodeptr.setNext(list1);
       list1 = list1.getNext();
        }
        else {
       nodeptr.setNext(list2);
       list2 = list2.getNext();
        }
        nodeptr = nodeptr.getNext();
   } // either list1 or list2 is null
   if (list1 == null)
        nodeptr.setNext(list2);
   else
        nodeptr.setNext(list1);
  
   return result;
    }
    @Override
   public Iterator<T> iterator(){
   //changed
   return new LinkedListIterator<T>(this); //pass in (ptr to) this LL
    }
    public Node<T> getFront(){
   return _Front;
    }
    public void setFront(Node<T> value){
   _Front = value;
    }
    public Node<T> getBack(){
   return _Back;
    }
    public void setBack(Node<T> value){
   _Back = value;
    }
}

Node.java

public class Node<T>{
    /**The element stored in the node */
    private T _Element;
  
    /**A reference to the next node of the list */
    private Node<T> _Next;

    /**Node Before this one.*/
    private Node<T> _Prev;
    public Node(T element, Node<T> next, Node<T> previous){
   this._Element = element;
   setNext(next);
   setPrev(previous);

   if(next != null){
        getNext().setPrev(this);
   }
   if(previous != null){
        getPrev().setNext(this);
   }
    }
    public T getElement() {
   return _Element;
    }
    public Node<T> getPrev(){
   return _Prev;
    }
    public void setPrev(Node<T> value){
   _Prev = value;
    }
    public Node<T> getNext(){
   return _Next;
    }
    public void setNext(Node<T> value){
   _Next = value;
    }
}


LinkedListIterator.java

import java.util.Iterator;
public class LinkedListIterator<T extends Comparable<? super T>>
    implements Iterator<T> {
    private Node<T> n;
    private LinkedList<T> list;
    public LinkedListIterator(LinkedList<T> list){
   n = list.getFront(); //forwards by default
   this.list = list;
    }
    @Override
    public boolean hasNext(){
   return n != null;
    }
    @Override
    public T next(){
   T saveElement = n.getElement(); //for output
   n = n.getNext(); //next
   return saveElement;
    }
    @Override
    public void remove() throws IllegalStateException{
   Node<T> target; //Node to be killed
   if(hasNext() ){ //n != null
        target = n.getPrev();
        if(target == null){ //could be an error, if no next() first
       throw new IllegalStateException();
        }
        if(target.getPrev() != null){ //two back; if not the beginning
       //normal middle-of-list removal
       target.getPrev().setNext(n);
       n.setPrev(target.getPrev());
        }
        else{//removing 1st node of many in LL
       //old front goes away, n is new front
       n.setPrev(null); //break second
       list.setFront(n); //target should soon be GCed.
        }
   }
   else{ //must be last element. n = null
        target = list.getBack();
        if(target == null){ //could be an error, if no next() first
       throw new IllegalStateException();
        }
        if(list.getFront() == list.getBack()){ //what if one node left?
       list.setFront(null);
       list.setBack( null);
        }
        else{ //normal removing of last node
       list.setBack(target.getPrev());
       list.getBack().setNext(null);
        }
   }
   target.setNext(null); //target used to think that it belonged
   target.setPrev(null); //now it does not
    } //hooray for automatic garbage collection!

    public T find(T target){
   //check every member, returning early when done
   while(hasNext()){
        T temp = next(); //save this ptr for next few lines
        if(target.equals(temp)){
       return temp;
        }
   }
   //if it made it this far, target not in list
   return null;
    }
    public void mergeSort(){
   list.sort();
    }
}

NoSuchElementException.java

public class NoSuchElementException extends Exception{
}