-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.go
171 lines (155 loc) · 5.37 KB
/
utils.go
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
package main
import (
"log"
"math"
"math/rand"
"time"
)
// reduceInfectiveEpochs returns true if person is no more infective
func reduceInfectiveEpochs(personPointer *person, ssnPointer *nationalHealthcareSystem, id uint32) bool {
if personPointer.InfectiveEpochs > 1 {
personPointer.InfectiveEpochs--
} else if personPointer.InfectiveEpochs == 1 {
personPointer.InfectiveEpochs--
personPointer.Infective = false
// at the end of the illness make it die with a certain probability
if bernoulli(deadRate) {
personPointer.Dead = true
} else {
personPointer.Survived = true
}
_ = removeFromSSN(ssnPointer, id)
return true
} else {
log.Println("ERROR", personPointer.InfectiveEpochs)
}
return false
}
// getInfected return a list of infected persons
func getInfected(networkPointer *bigNet) []int {
// infected is the returned slice
infected := make([]int, 0, 1)
for node := 0; node < nNodes; node++ {
// this condition allows to return only the actual infected people
if (*networkPointer)[node].Infective == true &&
(*networkPointer)[node].Survived == false &&
(*networkPointer)[node].Dead == false {
infected = append(infected, node)
}
}
return infected
}
// countInfected counts the number of infected people
// that satisfy the logic formula infective && survived && dead
func countInfected(networkPointer *bigNet, infective, survived, dead bool) int {
counter := 0
for node := 0; node < nNodes; node++ {
if (*networkPointer)[node].Infective == infective &&
(*networkPointer)[node].Survived == survived &&
(*networkPointer)[node].Dead == dead {
counter++
}
}
return counter
}
// countTotalInfected counts the total number of infected people
func countTotalInfected(networkPointer *bigNet) int {
counter := 0
for node := 0; node < nNodes; node++ {
if (*networkPointer)[node].Infective == true ||
(*networkPointer)[node].Survived == true ||
(*networkPointer)[node].Dead == true {
counter++
}
}
return counter
}
// resetNetwork reset the graph to random initial values without touching the shape
func resetNetwork(networkPointer *bigNet) {
for node := 0; node < nNodes; node++ {
// random seed
rand.Seed(time.Now().UnixNano())
// generate a random RO following a Normal Distribution
tmpR0 := int(math.Round(rand.NormFloat64()*stdR0 + medianR0))
if tmpR0 < 0 {
tmpR0 = 0
} // check if has been generated a negative number
// generating infective days array
infectiveDays := make([]int8, tmpR0)
for r := 0; r < tmpR0; r++ {
infectiveDays[r] = int8(rand.Intn(infectiveEpochs))
} // infect tmpR0 people during the infectiveEpochs period
// init parameters
(*networkPointer)[node].Infective = false
(*networkPointer)[node].Survived = false
(*networkPointer)[node].Dead = false
(*networkPointer)[node].InfectiveEpochs = infectiveEpochs
(*networkPointer)[node].InfectiveDays = infectiveDays
}
}
// bernoulli is a simple implementation that returns true with a certain pSuccess probability
func bernoulli(pSuccess float64) bool {
// random seed
rand.Seed(time.Now().UnixNano())
if rand.Intn(10000) < int(pSuccess*10000) {
return true
}
return false
}
// addToSSN returns false if it cannot be added to SSN
func addToSSN(ssnPointer *nationalHealthcareSystem, ID uint32, intensiveCare bool) bool {
if intensiveCare &&
(len((*ssnPointer).intensiveCareHospitalization)+1 <= (*ssnPointer).intensiveCare) {
// add to intensive care if is not full
(*ssnPointer).intensiveCareHospitalization = append((*ssnPointer).intensiveCareHospitalization, ID)
return true
} else if !intensiveCare &&
(len((*ssnPointer).subIntensiveCareHospitalization)+1 <= (*ssnPointer).subIntensiveCare) {
// add to sub intensive care if is not full
(*ssnPointer).subIntensiveCareHospitalization = append((*ssnPointer).subIntensiveCareHospitalization, ID)
return true
}
return false
}
// removeFromSSN
func removeFromSSN(ssnPointer *nationalHealthcareSystem, ID uint32) bool {
intensiveLen := len((*ssnPointer).intensiveCareHospitalization)
subIntensiveLen := len((*ssnPointer).subIntensiveCareHospitalization)
// check if ID is on intensive care
for i := 0; i < intensiveLen; i++ {
if (*ssnPointer).intensiveCareHospitalization[i] == ID {
(*ssnPointer).intensiveCareHospitalization = removeElementId((*ssnPointer).intensiveCareHospitalization, i)
return true
}
}
// ceck if ID is on sub intensive care
for i := 0; i < subIntensiveLen; i++ {
if (*ssnPointer).subIntensiveCareHospitalization[i] == ID {
(*ssnPointer).subIntensiveCareHospitalization = removeElementId((*ssnPointer).subIntensiveCareHospitalization, i)
return true
}
}
// not found on SSN
return false
}
// bernoulliHealthcare compute if Hospitalization is required and what kind
// Type of hospitalization: true intensive, false subintensive
func bernoulliHealthcare(pIntensive, pSubIntensive float64) (bool, bool) {
rand.Seed(time.Now().UnixNano()) //set a new casual seed
// check if requires intensive Care
intensiveHospitalization := bernoulli(pIntensive)
if !intensiveHospitalization {
// if not intensive care, check if sub Intensive care
subIntensiveHospitalization := bernoulli(pSubIntensive)
if !subIntensiveHospitalization {
// if any kind of hospitalization required
return false, false
}
return true, false
}
return true, true
}
// remove element at certain ID
func removeElementId(s []uint32, i int) []uint32 {
return append(s[:i], s[i+1:]...)
}