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{
}