-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFlu.java
178 lines (158 loc) · 7.04 KB
/
Flu.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package a4;
import java.util.Scanner;
import java.util.Set;
import common.Util;
import common.types.Tuple;
import common.types.Tuple5;
import io.ScannerUtils;
/** An instance represents a flu spreading and ultimately dying out among<br>
* a limited population (or killing everyone). <br>
* <br>
* Each Flu is created on a Network of people and with a chosen first patient. <br>
* Flu is runnable, but for the purposes of this project, it does not need to <br>
* be run on a separate thread.
*
* @author MPatashnik, revised by gries. */
public class Flu implements Runnable {
/** The graph on which this Flu is running. */
private Network network;
/** The tree representing this Flu spreading. */
private FluTree tree;
/** Number of time steps this Flu took to create dt. */
private int steps;
/** The Flu model: Statistics that determine the spread of the disease. */
private Statistics statistics;
/** How many chars to print per line in the running section. */
private static final int RUNNING_CHAR_COUNT_MAX= 50;
/** Used in printing the run progress. */
private int runningCharCount= 7;
/** Constructor: a new Flu on network nw with first patient fp and disease model s. */
public Flu(Network nw, Person fp, Statistics s) {
steps= 0;
network= nw;
fp.getSick(0);
tree= new FluTree(fp);
statistics= s;
}
/** Run the disease until no sick people remain. Print out info about running. */
public @Override void run() {
System.out.print("Running");
while (network.getPeopleOfType(Person.State.SICK).size() > 0) {
step();
}
System.out.println("Done.\n");
}
/** Perform a single step on the disease, using disease model statistics. <br>
* First, sick people may become immune with a certain probability. <br>
* Second, sick people become less healthy by 1, and if their health reaches 0, they die.<br>
* Third, sick people may spread the disease to one neighbor, with a certain probability. */
private void step() {
Set<Person> people= network.vertexSet();
System.out.print(".");
runningCharCount++ ;
if (runningCharCount > RUNNING_CHAR_COUNT_MAX) {
System.out.print("\n");
}
// For each sick person, make them immune with a certain probability
for (Person p : people) {
if (p.isSick() && statistics.personBecomesImmune()) {
p.getImmune(steps);
}
}
// For each sick person, deduct 1 from health and make death if health becomes 0
for (Person p : people) {
if (p.isSick()) {
p.reduceHealth(steps);
}
}
// For each sick person, spread the disease to one random neighbor with a
// certain probability.
for (Person p : people) {
if (p.isSick()) {
Person n= p.randomNeighbor();
if (n != null && n.isHealthy() && statistics.fluSpreadsToPerson()) {
n.getSick(steps);
tree.insert(n, p);
}
}
}
steps= steps + 1;
}
/** Read in the five statistic arguments from the console. <br>
* Return a Tuple5, with the following components: <br>
* - size: the number of people in the network <br>
* - maxHealth: how much health each person starts with <br>
* - connectionProbability: probability that two people are connected in the network <br>
* - sicknessProbability: probability that a sick person spreads the sickness <br>
*** to a neighbor in one time step <br>
* - immunizationProbability: probability that a sick person becomes immune in one time step */
private static Tuple5<Integer, Integer, Double, Double, Double> readArgs() {
Scanner scanner= ScannerUtils.defaultScanner();
int size= ScannerUtils.get(Integer.class, scanner, "Enter the size of the population: ",
"a positive non-zero integer", (i) -> i > 0);
int maxHealth= ScannerUtils.get(Integer.class, scanner,
"Enter the amount of health for each person: ",
"a positive non-zero integer", (i) -> i > 0);
double connectionProb= ScannerUtils.get(Double.class, scanner,
"Enter the probability of a connection: ",
"a double in the range [0,1]", (d) -> d >= 0 && d <= 1);
double sicknessProb= ScannerUtils.get(Double.class, scanner,
"Enter the probability of becoming sick: ",
"a double in the range [0,1]", (d) -> d >= 0 && d <= 1);
double immunizationProb= ScannerUtils.get(Double.class, scanner,
"Enter the probability of becoming immune: ",
"a double in the range [0,1]", (d) -> d >= 0 && d <= 1);
scanner.close();
return Tuple.of(size, maxHealth, connectionProb, sicknessProb, immunizationProb);
}
/** Run Flu on the arguments listed in args. <br>
* If args doesn't match the pattern below, read in arguments via the console by using
* readArgs().
*
* Then, call disease.run() and create a FluFrame showing the created FluTree.
*
* args should be an array of <br>
*
* [size, maxHealth, connection probability, sickness probability, immunization probability],
*
* or unused (any value). If not used, the user is prompted for input in the console. */
public static void main(String[] args) {
// Get arguments
int size= 10;
int maxHealth= 5;
double connectionProbability= 0.7;
double sicknessProbability= 0.5;
double immunizationProbability= 0.1;
try {
// Attempt to read from args array passed in
size= Integer.parseInt(args[0]);
maxHealth= Integer.parseInt(args[1]);
connectionProbability= Double.parseDouble(args[2]);
sicknessProbability= Double.parseDouble(args[3]);
immunizationProbability= Double.parseDouble(args[4]);
} catch (Exception e) {
// If too few or wrong type, read from scanner
Tuple5<Integer, Integer, Double, Double, Double> args2= readArgs();
size= args2._1;
maxHealth= args2._2;
connectionProbability= args2._3;
sicknessProbability= args2._4;
immunizationProbability= args2._5;
}
// Set defaults and create the Network, Statistics, and Flu objects
System.out.print("\nSetting up ");
System.out.print(".");
Network n= new Network(size, maxHealth, connectionProbability);
System.out.print(".");
Statistics s= new Statistics(sicknessProbability, immunizationProbability);
System.out.print(".");
Flu d= new Flu(n, Util.randomElement(n.vertexSet()), s);
System.out.println("Done.");
d.run();
System.out.println(d.tree.toStringVerbose() + "\n");
for (Person p : d.network.getPeopleOfType(Person.State.HEALTHY)) {
System.out.println(p);
}
FluJFrame.show(d.tree, d.steps);
}
}