-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsobol_full.py
129 lines (103 loc) · 3.46 KB
/
sobol_full.py
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
"""
Performs full Sobol analysis by running simulations
The process flow is as follows:
main() ->
get_all_outcomes() ->
get_simrun_outcome() ->
Nature() ->
summarize() ->
analyze_sobol()
"""
import gc
from multiprocessing import Pool
from copy import deepcopy
import numpy as np
from numpy.typing import NDArray
from SALib.sample import sobol as sb
from SALib.analyze import sobol
from models import Nature
NUM_SCEN = 2**11
PARAMS = {
"p": 5, "n": 4, "t": 500, "nsoc": 4, "deg": 2,
"xi": 1.0, "wf": 1.0, "goals": (1.0, 1.0),
"normalize": True, "precompute": True
}
def sample_saltelli(num_scenarios: int, prblm) -> NDArray[np.int8]:
"""
Quasi-randomly generates parameter combinations
in the multidimensional space with low discrepancy
"""
param_sets = sb.sample(prblm, num_scenarios, calc_second_order=True)
discrete = param_sets[:,:-2].round()
continuous = param_sets[:,-2:].round(1)
param_sets = np.hstack((discrete, continuous))
return param_sets
def summarize(outcm):
"""Calculates the statistics of interest"""
f50 = outcm[:50].mean()
f100 = outcm[:100].mean()
f500 = outcm.mean()
fmax = outcm.max()
return [f50, f100, f500, fmax]
def analyze_sobol(prblm, values, fname):
vals = ["f50", "f100", "f500", "fmax"]
with open(fname, "w") as file:
for i,val in enumerate(vals):
indices = sobol.analyze(prblm, values[:,i])
file.write(f"{val}:\n")
file.write(f"{indices}\n\n")
def get_simrun_outcome(prms):
"""Run a single simulation give params"""
parameters = deepcopy(PARAMS) # deep copy just in case
parameters['kcs'] = (int(prms[0]), int(prms[1]), int(prms[2]))
parameters['coord'] = int(prms[3])
parameters['apc'] = (int(prms[4]), 2, int(prms[5]))
parameters['net'] = int(prms[6])
parameters['tm'] = int(prms[7])
parameters['w'] = prms[8]
parameters['rho'] = prms[9]
print(parameters)
nature = Nature(**parameters)
np.random.seed()
nature.initialize()
nature.play()
perfs = nature.organization.performances.mean(axis=1)
syncs = nature.organization.synchronies
perfSummary = summarize(perfs)
syncSummary = summarize(syncs)
del nature
gc.collect()
return perfSummary, syncSummary
def get_all_outcomes(prblm):
'''Central place to run loops; multiprocessing needed here'''
param_sets = sample_saltelli(NUM_SCEN, prblm)
print(f"Params shape is {param_sets.shape}")
with Pool(2) as pool:
results = pool.map(get_simrun_outcome, param_sets)
perfs = [res[0] for res in results]
syncs = [res[1] for res in results]
#perfs = []
#syncs = []
#for i,params in enumerate(param_sets):
# print(i)
# perf, sync = get_simrun_outcome(params)
# perfs.append(perf)
# syncs.append(sync)
#
# if i > 0 and i % 4 == 0 :
# gc.collect()
#
return np.array(perfs), np.array(syncs)
def main():
"""main function"""
problem = {
"num_vars": 10,
"names": [ "k", "c", "s", "coordination", "alt", "comp", "network", "tm", "w", "correlation" ],
"bounds": [ [0,3], [0,4], [0,3], [0,2], [2,4], [2,4], [1,4], [10,100], [0,1], [0.5,1] ]
}
perfs, syncs = get_all_outcomes(problem)
analyze_sobol(problem, perfs, "perfsens.txt")
analyze_sobol(problem, syncs, "syncsens.txt")
print("Done")
if __name__=="__main__":
main()