1 | package tudelft.mentalhealth.motivatepersisting;
|
---|
2 |
|
---|
3 | import java.io.BufferedReader;
|
---|
4 | import java.io.IOException;
|
---|
5 | import java.io.InputStream;
|
---|
6 | import java.io.InputStreamReader;
|
---|
7 | import java.util.Collection;
|
---|
8 | import java.util.HashMap;
|
---|
9 | import java.util.Map;
|
---|
10 |
|
---|
11 | import tudelft.utilities.statistic.WeightedSet;
|
---|
12 |
|
---|
13 | /**
|
---|
14 | * Contains table 2: Probabilities of a given category in a given situation,
|
---|
15 | * defined by PCL score and Trust. Immutable. Singleton to avoid re-loading the
|
---|
16 | * table repeatedly.
|
---|
17 | *
|
---|
18 | * This is read from a text file that has similar layout as in
|
---|
19 | * Dataset_Database.pdf. The first and second column are category and
|
---|
20 | * sub-category, the remaining 9 columns are for Dropping(high,med,low),
|
---|
21 | * stable(high,med,low) and rising(high,med,low).
|
---|
22 | */
|
---|
23 | class ProbOfCategoriesPerSituation {
|
---|
24 | private static ProbOfCategoriesPerSituation instance = null;
|
---|
25 |
|
---|
26 | private final Map<Category, Map<Subcategory, Map<Situation, Double>>> probabilities = new HashMap<>();
|
---|
27 |
|
---|
28 | private ProbOfCategoriesPerSituation() {
|
---|
29 | readTable();
|
---|
30 | }
|
---|
31 |
|
---|
32 | private void readTable() {
|
---|
33 | InputStream is = MeanNrStatements.class
|
---|
34 | .getResourceAsStream("ProbOfCategories.csv");
|
---|
35 |
|
---|
36 | BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
---|
37 | reader.lines().forEach(line -> addLine(line));
|
---|
38 | }
|
---|
39 |
|
---|
40 | private void addLine(String line) {
|
---|
41 | if (line.isEmpty())
|
---|
42 | return;
|
---|
43 | String[] values = line.split(",");
|
---|
44 | Category cat = Category.valueOf(values[0].trim());
|
---|
45 | Subcategory subcat;
|
---|
46 | String value1 = values[1].trim();
|
---|
47 | if (value1.isEmpty()) {
|
---|
48 | subcat = Subcategory.ALL;
|
---|
49 | } else {
|
---|
50 | subcat = Subcategory.valueOf(value1);
|
---|
51 | if (!cat.isSubcategoryAllowed(subcat)) {
|
---|
52 | throw new IllegalArgumentException(
|
---|
53 | "internal error reading csv: incorrect category-subcategory relation encountered");
|
---|
54 | }
|
---|
55 | }
|
---|
56 |
|
---|
57 | if (!probabilities.containsKey(cat)) {
|
---|
58 | probabilities.put(cat, new HashMap<>());
|
---|
59 | }
|
---|
60 | if (!probabilities.get(cat).containsKey(subcat)) {
|
---|
61 | probabilities.get(cat).put(subcat, new HashMap<>());
|
---|
62 | }
|
---|
63 | Map<Situation, Double> situations = probabilities.get(cat).get(subcat);
|
---|
64 | // the remaining 9 columns are the values for various PCL/Trust combi's.
|
---|
65 | // Decode.
|
---|
66 | int col = 2;
|
---|
67 | for (PclTrend pcl : PclTrend.values()) {
|
---|
68 | for (Trust trust : Trust.values()) {
|
---|
69 | situations.put(new Situation(pcl, trust),
|
---|
70 | Double.valueOf(values[col++]));
|
---|
71 | }
|
---|
72 | }
|
---|
73 | }
|
---|
74 |
|
---|
75 | /**
|
---|
76 | *
|
---|
77 | * @return the instance of this class
|
---|
78 | * @throws IOException
|
---|
79 | */
|
---|
80 | public static ProbOfCategoriesPerSituation instance() {
|
---|
81 | if (instance == null) {
|
---|
82 | instance = new ProbOfCategoriesPerSituation();
|
---|
83 | }
|
---|
84 | return instance;
|
---|
85 | }
|
---|
86 |
|
---|
87 | /**
|
---|
88 | *
|
---|
89 | * @param cat the {@link Category} of the planned statement
|
---|
90 | * @param situation the patient {@link Situation}
|
---|
91 | * @return a random chosen subcategory of the given category based on a
|
---|
92 | * weighted randomized selection. The random choice is weighted by
|
---|
93 | * the weights in probabilities table.
|
---|
94 | */
|
---|
95 | public Subcategory getweightedRandomSubcategory(Category category,
|
---|
96 | Situation situation) {
|
---|
97 | Map<Subcategory, Double> map = new HashMap<>();
|
---|
98 | for (Subcategory subcat : category.getSubCategories()) {
|
---|
99 | map.put(subcat, get(category, subcat, situation));
|
---|
100 | }
|
---|
101 | return new WeightedSet<>(map).getRandom();
|
---|
102 |
|
---|
103 | }
|
---|
104 |
|
---|
105 | /**
|
---|
106 | *
|
---|
107 | * @param situation the {@link Situation} to generate a random Category for
|
---|
108 | * @param excludes list of {@link Category} that are excluded for selection
|
---|
109 | * @return a weighted randomly chosen {@link Category} that is not in
|
---|
110 | * excludes.
|
---|
111 | */
|
---|
112 | public Category getWeightedRandomCategory(Collection<Category> excludes,
|
---|
113 | Situation situation) {
|
---|
114 | Map<Category, Double> map = new HashMap<>();
|
---|
115 | for (Category category : Category.values()) {
|
---|
116 | if (!(excludes.contains(category))) {
|
---|
117 | map.put(category, get(category, Subcategory.ALL, situation));
|
---|
118 | }
|
---|
119 | }
|
---|
120 | return new WeightedSet<>(map).getRandom();
|
---|
121 | }
|
---|
122 |
|
---|
123 | @Override
|
---|
124 | public String toString() {
|
---|
125 | return probabilities.toString();
|
---|
126 | }
|
---|
127 |
|
---|
128 | /**
|
---|
129 | *
|
---|
130 | * @param cat the {@link Category} of a possible statement to motivate
|
---|
131 | * @param subcat the {@link Subcategory} of a possible statement to be
|
---|
132 | * given
|
---|
133 | * @param situation the situation in which the patient is.
|
---|
134 | * @return the probability that a statement is given for given
|
---|
135 | * situation,cat&subcat.
|
---|
136 | */
|
---|
137 | public Double get(Category cat, Subcategory subcat, Situation situation) {
|
---|
138 | return probabilities.get(cat).get(subcat).get(situation);
|
---|
139 | }
|
---|
140 |
|
---|
141 | /**
|
---|
142 | * If this has no subcategory, returns category with ALL subcategory. If
|
---|
143 | * this has a subcategory, returns
|
---|
144 | * {@link #getweightedRandomSubcategory(cat, situation)}.
|
---|
145 | *
|
---|
146 | * @param cat the Category of the planned statement
|
---|
147 | * @param situation the patient {@link Situation}
|
---|
148 | * @return subcategory according to protocols
|
---|
149 | */
|
---|
150 | public Subcategory selectSubcategory(Category cat, Situation situation) {
|
---|
151 | if (cat.getSubCategories().isEmpty()) {
|
---|
152 | return Subcategory.ALL;
|
---|
153 | }
|
---|
154 | return getweightedRandomSubcategory(cat, situation);
|
---|
155 | }
|
---|
156 |
|
---|
157 | }
|
---|