-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmain_comparison.py
272 lines (245 loc) · 7.6 KB
/
main_comparison.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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
"""
This script runs 100 simulations per MillerDynamics such as MillerDynamics.EXPLICIT, MillerDynamics.ROOT_EXPLICIT,
MillerDynamics.ROOT_IMPLICIT, MillerDynamics.IMPLICIT, MillerDynamics.IMPLICIT_TAU_DRIVEN_QDDOT, ...
It does it with multiprocessing.Pool() to compare explicit and implicit formulations and equations of motion namely,
full-body dynamics and free-floating base dynamics.
This script was originally run on an AMD Ryzen 9 5950X processor and with 128 Go RAM.
"""
import os
from pathlib import Path
from typing import Union
import pickle
from multiprocessing import Pool, cpu_count
from datetime import date
import miller_run
from bioptim import OdeSolver
from custom_dynamics.enums import MillerDynamics
Date = date.today()
Date = Date.strftime("%d-%m-%y")
out_path_raw = "../OnDynamicsForSommersaults_results/raw_" + Date
try:
os.mkdir(out_path_raw)
except:
print("../OnDynamicsForSommersaults_results/raw_" + Date + " is already created ")
cpu_number = cpu_count()
model_str = "Model_JeCh_15DoFs.bioMod"
n_shooting = (125, 25)
nstep = 5
def generate_calls(
n: Union[int, list],
Date,
n_shooting: tuple,
dynamics_types: list,
ode_solver: list,
nstep: int,
n_threads: int,
out_path_raw: str,
model_str: str,
extra_obj: bool,
) -> list:
"""
Generate the list of calls to be used in multiprocessing
Parameters
----------
n : Union[int, list]
The int of list of irand to be run
Date : str
The date of the run
n_shooting : tuple
The number of shooting points for each phase
dynamics_types : list
The list of dynamics types to be run such as MillerDynamics.EXPLICIT, MillerDynamics.IMPLICIT, MillerDynamics.EXPLICIT_IMPLICIT
ode_solver : list
The list of OdeSolver to be run such as OdeSolver.RK4, OdeSolver.RK2
nstep : int
The number of intermediate steps between two shooting points
n_threads : int
The number of threads to be used
out_path_raw : str
The path to store the raw results
model_str : str
The path to the bioMod model
extra_obj : bool
Whether to run with the extra objective or not (minimizing extra controls for implicit formulations)
Returns
-------
calls: list
The list of calls to be run
"""
if isinstance(n, int):
rand_loop = range(n)
else:
rand_loop = n
calls = []
for i, dynamics_type in enumerate(dynamics_types):
for i_rand in rand_loop: # Should be 100
calls.append(
[
Date,
i_rand,
n_shooting,
dynamics_type,
ode_solver[i],
nstep,
n_threads,
out_path_raw,
model_str,
extra_obj,
]
)
return calls
def run_pool(calls: list, pool_nb: int):
"""
Run the pool of processes
Parameters
----------
calls : list
The list of calls to be run
pool_nb : int
The number of processes to be used in parallel
"""
with Pool(pool_nb) as p: # should be 4
p.map(miller_run.main, calls)
def run_the_missing_ones(
out_path_raw: str,
Date,
n_shooting: tuple,
dynamics_types: list,
ode_solver: list,
nstep: int,
n_threads: int,
model_str: str,
extra_obj: bool,
pool_nb: int,
):
"""
This function is used to run the process that were not run during the previous pool of processes
Parameters
----------
out_path_raw : str
The path to store the raw results
Date : str
The date of the run
n_shooting : tuple
The number of shooting points for each phase
dynamics_types : list
The list of dynamics types to be run such as MillerDynamics.EXPLICIT, MillerDynamics.IMPLICIT, MillerDynamics.ROOT_EXPLICIT
ode_solver : list
The list of OdeSolver to be run such as OdeSolver.RK4, OdeSolver.RK2
nstep : int
The number of intermediate steps between two shooting points
n_threads : int
The number of threads to be used
model_str : str
The path to the bioMod model
extra_obj : bool
Whether to run with the extra objective or not (minimizing extra controls for implicit formulations)
"""
# Run the one that did not run
files = os.listdir(out_path_raw)
files.sort()
new_calls = {dynamics_types[0].value: [], dynamics_types[1].value: []}
for i, file in enumerate(files):
if file.endswith(".pckl"):
p = Path(f"{out_path_raw}/{file}")
file_path = open(p, "rb")
data = pickle.load(file_path)
if (
data["dynamics_type"].value == dynamics_types[0].value
or data["dynamics_type"].value == dynamics_types[1].value
):
new_calls[data["dynamics_type"].value].append(data["irand"])
list_100 = [i for i in range(0, 100)]
dif_list = list(set(list_100) - set(new_calls[dynamics_types[0].value]))
if dif_list:
calls = generate_calls(
dif_list,
Date,
n_shooting,
[dynamics_types[1]],
[ode_solver[1]],
nstep,
n_threads,
out_path_raw,
model_str,
extra_obj,
)
run_pool(calls, pool_nb)
dif_list = list(set(list_100) - set(new_calls[dynamics_types[1].value]))
if dif_list:
calls = generate_calls(
dif_list,
Date,
n_shooting,
[dynamics_types[1]],
[ode_solver[1]],
nstep,
n_threads,
out_path_raw,
model_str,
extra_obj,
)
run_pool(calls, pool_nb)
# Running explicit formulations full-body dynamics and free-floating dynamics
n_threads = 4
ode_solver = [OdeSolver.RK4, OdeSolver.RK4]
dynamics_types = [MillerDynamics.EXPLICIT, MillerDynamics.ROOT_EXPLICIT]
my_calls = generate_calls(
100,
Date,
n_shooting,
dynamics_types,
ode_solver,
nstep,
n_threads,
out_path_raw,
model_str,
False,
)
my_pool_number = int(cpu_number / n_threads)
run_pool(my_calls, my_pool_number)
run_the_missing_ones(
out_path_raw, Date, n_shooting, dynamics_types, ode_solver, nstep, n_threads, model_str, False, my_pool_number
)
# Running implicit formulations full-body dynamics and free-floating dynamics
n_threads = 1
ode_solver = [OdeSolver.RK2, OdeSolver.RK2]
dynamics_types = [MillerDynamics.IMPLICIT, MillerDynamics.ROOT_IMPLICIT]
my_calls = generate_calls(
100,
Date,
n_shooting,
dynamics_types,
ode_solver,
nstep,
n_threads,
out_path_raw,
model_str,
True,
)
my_pool_number = int(cpu_number / n_threads)
run_pool(my_calls, my_pool_number)
run_the_missing_ones(
out_path_raw, Date, n_shooting, dynamics_types, ode_solver, nstep, n_threads, model_str, True, my_pool_number
)
# Running implicit formulations with jerks as extra controls full-body dynamics and free-floating dynamics
n_threads = 1 # Should be 8
ode_solver = [OdeSolver.RK4, OdeSolver.RK4]
dynamics_types = [MillerDynamics.IMPLICIT_TAU_DRIVEN_QDDDOT, MillerDynamics.ROOT_IMPLICIT_QDDDOT]
my_calls = generate_calls(
100,
Date,
n_shooting,
dynamics_types,
ode_solver,
nstep,
n_threads,
out_path_raw,
model_str,
True,
)
my_pool_number = int(cpu_number / n_threads)
run_pool(my_calls, my_pool_number)
run_the_missing_ones(
out_path_raw, Date, n_shooting, dynamics_types, ode_solver, nstep, n_threads, model_str, True, my_pool_number
)