-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimulation.py
229 lines (183 loc) · 8.06 KB
/
simulation.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
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# -*- coding: utf-8 -*-
"""
:Author: Dominic Hunt
"""
import logging
import copy
import fire
import pandas as pd
import numpy as np
import outputting
from taskGenerator import TaskGeneration
from modelGenerator import ModelGen
def run(task_name='Basic',
task_changing_properties=None,
task_constant_properties=None,
model_name='QLearn',
model_changing_properties=None,
model_constant_properties=None,
model_changing_properties_repetition=1,
label=None,
config_file=None,
output_path=None,
pickle=False,
min_log_level='INFO',
numpy_error_level="log"):
"""
A framework for letting models interact with tasks and record the data
Parameters
----------
task_name : string
The name of the file where a tasks.taskTemplate.Task class can be found. Default ``Basic``
task_changing_properties : dictionary of floats or lists of floats
Parameters are the options that you are or are likely to change across task instances. When a parameter
contains a list, an instance of the task will be created for every combination of this parameter with all
the others. Default ``None``
task_constant_properties : dictionary of float, string or binary valued elements
These contain all the the task options that describe the task being studied but do not vary across
task instances. Default ``None``
model_name : string
The name of the file where a model.modelTemplate.Model class can be found. Default ``QLearn``
model_changing_properties : dictionary containing floats or lists of floats, optional
Parameters are the options that you are or are likely to change across
model instances. When a parameter contains a list, an instance of the
model will be created for every combination of this parameter with
all the others. Default ``None``
model_constant_properties : dictionary of float, string or binary valued elements, optional
These contain all the the model options that define the version
of the model being studied. Default ``None``
model_changing_properties_repetition : int, optional
The number of times each parameter combination is repeated.
config_file : string, optional
The file name and path of a ``.yaml`` configuration file. Overrides all other parameters if found.
Default ``None``
output_path : string, optional
The path that will be used for the run output. Default ``None``
pickle : bool, optional
If true the data for each model, task and participant is recorded.
Default is ``False``
label : string, optional
The label for the simulation. Default ``None``, which means nothing will be saved
min_log_level : str, optional
Defines the level of the log from (``DEBUG``, ``INFO``, ``WARNING``, ``ERROR``, ``CRITICAL``). Default ``INFO``
numpy_error_level : {'log', 'raise'}
Defines the response to numpy errors. Default ``log``. See numpy.seterr
See Also
--------
tasks.taskTemplate, model.modelTemplate
"""
config = copy.deepcopy(locals())
tasks = TaskGeneration(task_name=task_name,
parameters=task_changing_properties,
other_options=task_constant_properties)
if model_changing_properties_repetition > 1:
repeated_key = model_changing_properties.keys()[0]
repeated_values = np.repeat(model_changing_properties[repeated_key], model_changing_properties_repetition)
model_changing_properties[repeated_key] = repeated_values.tolist()
models = ModelGen(model_name=model_name,
parameters=model_changing_properties,
other_options=model_constant_properties)
with outputting.Saving(config=config) as file_name_generator:
logger = logging.getLogger('Overview')
simID = 0
message = "Beginning the simulation set"
logger.debug(message)
for task_number in tasks.iter_task_ID():
for model in models:
task = tasks.new_task(task_number)
log_simulation_parameters(task.params(), model.params(), simID=str(simID))
message = "Beginning task"
logger.debug(message)
for state in task:
model.observe(state)
action = model.action()
task.receiveAction(action)
response = task.feedback()
model.feedback(response)
task.proceed()
model.setsimID(str(simID))
message = "Task completed"
logger.debug(message)
if file_name_generator is not None:
record_simulation(file_name_generator,
task.returnTaskState(),
model.returnTaskState(),
str(simID), pickle=pickle)
simID += 1
def record_simulation(file_name_generator, task_data, model_data, simID, pickle=False):
"""
Records the data from an task-model run. Creates a pickled version
Parameters
----------
file_name_generator : function
Creates a new file with the name <handle> and the extension <extension>. It takes two string parameters: (``handle``, ``extension``) and
returns one ``fileName`` string
task_data : dict
The data from the task
model_data : dict
The data from the model
simID : str
The label identifying the simulation
pickle : bool, optional
If true the data for each model, task and participant is recorded.
Default is ``False``
See Also
--------
pickleLog : records the picked data
"""
logger = logging.getLogger('Framework')
message = "Beginning simulation output processing"
logger.debug(message)
label = "_sim-" + simID
message = "Store data for simulation " + simID
logger.debug(message)
csv_model_simulation(model_data, simID, file_name_generator)
if pickle:
outputting.pickleLog(task_data, file_name_generator, "_taskData" + label)
outputting.pickleLog(model_data, file_name_generator, "_modelData" + label)
def log_simulation_parameters(task_parameters, model_parameters, simID):
"""
Writes to the log the description and the label of the task and model
Parameters
----------
task_parameters : dict
The task parameters
model_parameters : dict
The model parameters
simID : string
The identifier for each simulation.
See Also
--------
recordSimParams : Records these parameters for later use
"""
task_description = task_parameters.pop('Name') + ": "
task_descriptors = [k + ' = ' + repr(v) for k, v in task_parameters.items()]
task_description += ", ".join(task_descriptors)
model_description = model_parameters.pop('Name') + ": "
model_descriptors = [k + ' = ' + repr(v) for k, v in model_parameters.items()]
model_description += ", ".join(model_descriptors)
message = "Simulation " + simID + " contains the task " + task_description + "."
message += "The model used is " + model_description + "."
logger_sim = logging.getLogger('Simulation')
logger_sim.info(message)
def csv_model_simulation(modelData, simID, file_name_generator):
# type: (dict, str, function) -> None
"""
Saves the fitting data to a CSV file
Parameters
----------
modelData : dict
The data from the model
simID : string
The identifier for the simulation
file_name_generator : function
Creates a new file with the name <handle> and the extension <extension>. It takes two string parameters: (``handle``, ``extension``) and
returns one ``fileName`` string
"""
data = outputting.newListDict(modelData)
record = pd.DataFrame(data)
name = "data/modelSim_" + simID
outputFile = file_name_generator(name, 'csv')
record.to_csv(outputFile)
if __name__ == '__main__':
fire.Fire(run)