sierra-research 1.3.6__py3-none-any.whl → 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sierra/__init__.py +3 -3
- sierra/core/__init__.py +3 -3
- sierra/core/batchroot.py +223 -0
- sierra/core/cmdline.py +681 -1057
- sierra/core/compare.py +11 -0
- sierra/core/config.py +96 -88
- sierra/core/engine.py +306 -0
- sierra/core/execenv.py +380 -0
- sierra/core/expdef.py +11 -0
- sierra/core/experiment/__init__.py +1 -0
- sierra/core/experiment/bindings.py +150 -101
- sierra/core/experiment/definition.py +414 -245
- sierra/core/experiment/spec.py +83 -85
- sierra/core/exproot.py +44 -0
- sierra/core/generators/__init__.py +10 -0
- sierra/core/generators/experiment.py +528 -0
- sierra/core/generators/generator_factory.py +138 -137
- sierra/core/graphs/__init__.py +23 -0
- sierra/core/graphs/bcbridge.py +94 -0
- sierra/core/graphs/heatmap.py +245 -324
- sierra/core/graphs/pathset.py +27 -0
- sierra/core/graphs/schema.py +77 -0
- sierra/core/graphs/stacked_line.py +341 -0
- sierra/core/graphs/summary_line.py +506 -0
- sierra/core/logging.py +3 -2
- sierra/core/models/__init__.py +3 -1
- sierra/core/models/info.py +19 -0
- sierra/core/models/interface.py +52 -122
- sierra/core/pipeline/__init__.py +2 -5
- sierra/core/pipeline/pipeline.py +228 -126
- sierra/core/pipeline/stage1/__init__.py +10 -0
- sierra/core/pipeline/stage1/pipeline_stage1.py +45 -31
- sierra/core/pipeline/stage2/__init__.py +10 -0
- sierra/core/pipeline/stage2/pipeline_stage2.py +8 -11
- sierra/core/pipeline/stage2/runner.py +401 -0
- sierra/core/pipeline/stage3/__init__.py +12 -0
- sierra/core/pipeline/stage3/gather.py +321 -0
- sierra/core/pipeline/stage3/pipeline_stage3.py +37 -84
- sierra/core/pipeline/stage4/__init__.py +12 -2
- sierra/core/pipeline/stage4/pipeline_stage4.py +36 -354
- sierra/core/pipeline/stage5/__init__.py +12 -0
- sierra/core/pipeline/stage5/pipeline_stage5.py +33 -208
- sierra/core/pipeline/yaml.py +48 -0
- sierra/core/plugin.py +529 -62
- sierra/core/proc.py +11 -0
- sierra/core/prod.py +11 -0
- sierra/core/ros1/__init__.py +5 -1
- sierra/core/ros1/callbacks.py +22 -21
- sierra/core/ros1/cmdline.py +59 -88
- sierra/core/ros1/generators.py +159 -175
- sierra/core/ros1/variables/__init__.py +3 -0
- sierra/core/ros1/variables/exp_setup.py +122 -116
- sierra/core/startup.py +106 -76
- sierra/core/stat_kernels.py +4 -5
- sierra/core/storage.py +13 -32
- sierra/core/trampoline.py +30 -0
- sierra/core/types.py +116 -71
- sierra/core/utils.py +103 -106
- sierra/core/variables/__init__.py +1 -1
- sierra/core/variables/base_variable.py +12 -17
- sierra/core/variables/batch_criteria.py +387 -481
- sierra/core/variables/builtin.py +135 -0
- sierra/core/variables/exp_setup.py +19 -39
- sierra/core/variables/population_size.py +72 -76
- sierra/core/variables/variable_density.py +44 -68
- sierra/core/vector.py +1 -1
- sierra/main.py +256 -88
- sierra/plugins/__init__.py +119 -0
- sierra/plugins/compare/__init__.py +14 -0
- sierra/plugins/compare/graphs/__init__.py +19 -0
- sierra/plugins/compare/graphs/cmdline.py +120 -0
- sierra/plugins/compare/graphs/comparator.py +291 -0
- sierra/plugins/compare/graphs/inter_controller.py +531 -0
- sierra/plugins/compare/graphs/inter_scenario.py +297 -0
- sierra/plugins/compare/graphs/namecalc.py +53 -0
- sierra/plugins/compare/graphs/outputroot.py +73 -0
- sierra/plugins/compare/graphs/plugin.py +147 -0
- sierra/plugins/compare/graphs/preprocess.py +172 -0
- sierra/plugins/compare/graphs/schema.py +37 -0
- sierra/plugins/engine/__init__.py +14 -0
- sierra/plugins/engine/argos/__init__.py +18 -0
- sierra/plugins/{platform → engine}/argos/cmdline.py +144 -151
- sierra/plugins/{platform/argos/variables → engine/argos/generators}/__init__.py +5 -0
- sierra/plugins/engine/argos/generators/engine.py +394 -0
- sierra/plugins/engine/argos/plugin.py +393 -0
- sierra/plugins/{platform/argos/generators → engine/argos/variables}/__init__.py +5 -0
- sierra/plugins/engine/argos/variables/arena_shape.py +183 -0
- sierra/plugins/engine/argos/variables/cameras.py +240 -0
- sierra/plugins/engine/argos/variables/constant_density.py +112 -0
- sierra/plugins/engine/argos/variables/exp_setup.py +82 -0
- sierra/plugins/{platform → engine}/argos/variables/physics_engines.py +83 -87
- sierra/plugins/engine/argos/variables/population_constant_density.py +178 -0
- sierra/plugins/engine/argos/variables/population_size.py +115 -0
- sierra/plugins/engine/argos/variables/population_variable_density.py +123 -0
- sierra/plugins/engine/argos/variables/rendering.py +108 -0
- sierra/plugins/engine/ros1gazebo/__init__.py +18 -0
- sierra/plugins/engine/ros1gazebo/cmdline.py +175 -0
- sierra/plugins/{platform/ros1robot → engine/ros1gazebo}/generators/__init__.py +5 -0
- sierra/plugins/engine/ros1gazebo/generators/engine.py +125 -0
- sierra/plugins/engine/ros1gazebo/plugin.py +404 -0
- sierra/plugins/engine/ros1gazebo/variables/__init__.py +15 -0
- sierra/plugins/engine/ros1gazebo/variables/population_size.py +214 -0
- sierra/plugins/engine/ros1robot/__init__.py +18 -0
- sierra/plugins/engine/ros1robot/cmdline.py +159 -0
- sierra/plugins/{platform/ros1gazebo → engine/ros1robot}/generators/__init__.py +4 -0
- sierra/plugins/engine/ros1robot/generators/engine.py +95 -0
- sierra/plugins/engine/ros1robot/plugin.py +410 -0
- sierra/plugins/{hpc/local → engine/ros1robot/variables}/__init__.py +5 -0
- sierra/plugins/engine/ros1robot/variables/population_size.py +146 -0
- sierra/plugins/execenv/__init__.py +11 -0
- sierra/plugins/execenv/hpc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/adhoc/plugin.py +131 -0
- sierra/plugins/execenv/hpc/cmdline.py +137 -0
- sierra/plugins/execenv/hpc/local/__init__.py +18 -0
- sierra/plugins/execenv/hpc/local/cmdline.py +31 -0
- sierra/plugins/execenv/hpc/local/plugin.py +145 -0
- sierra/plugins/execenv/hpc/pbs/__init__.py +18 -0
- sierra/plugins/execenv/hpc/pbs/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/pbs/plugin.py +121 -0
- sierra/plugins/execenv/hpc/slurm/__init__.py +18 -0
- sierra/plugins/execenv/hpc/slurm/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/slurm/plugin.py +133 -0
- sierra/plugins/execenv/prefectserver/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/dockerremote/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/plugin.py +132 -0
- sierra/plugins/execenv/prefectserver/flow.py +66 -0
- sierra/plugins/execenv/prefectserver/local/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/local/cmdline.py +29 -0
- sierra/plugins/execenv/prefectserver/local/plugin.py +133 -0
- sierra/plugins/{hpc/adhoc → execenv/robot}/__init__.py +1 -0
- sierra/plugins/execenv/robot/turtlebot3/__init__.py +18 -0
- sierra/plugins/execenv/robot/turtlebot3/plugin.py +204 -0
- sierra/plugins/expdef/__init__.py +14 -0
- sierra/plugins/expdef/json/__init__.py +14 -0
- sierra/plugins/expdef/json/plugin.py +504 -0
- sierra/plugins/expdef/xml/__init__.py +14 -0
- sierra/plugins/expdef/xml/plugin.py +386 -0
- sierra/{core/hpc → plugins/proc}/__init__.py +1 -1
- sierra/plugins/proc/collate/__init__.py +15 -0
- sierra/plugins/proc/collate/cmdline.py +47 -0
- sierra/plugins/proc/collate/plugin.py +271 -0
- sierra/plugins/proc/compress/__init__.py +18 -0
- sierra/plugins/proc/compress/cmdline.py +47 -0
- sierra/plugins/proc/compress/plugin.py +123 -0
- sierra/plugins/proc/decompress/__init__.py +18 -0
- sierra/plugins/proc/decompress/plugin.py +96 -0
- sierra/plugins/proc/imagize/__init__.py +15 -0
- sierra/plugins/proc/imagize/cmdline.py +49 -0
- sierra/plugins/proc/imagize/plugin.py +270 -0
- sierra/plugins/proc/modelrunner/__init__.py +16 -0
- sierra/plugins/proc/modelrunner/plugin.py +250 -0
- sierra/plugins/proc/statistics/__init__.py +15 -0
- sierra/plugins/proc/statistics/cmdline.py +64 -0
- sierra/plugins/proc/statistics/plugin.py +390 -0
- sierra/plugins/{hpc → prod}/__init__.py +1 -0
- sierra/plugins/prod/graphs/__init__.py +18 -0
- sierra/plugins/prod/graphs/cmdline.py +269 -0
- sierra/plugins/prod/graphs/collate.py +279 -0
- sierra/plugins/prod/graphs/inter/__init__.py +13 -0
- sierra/plugins/prod/graphs/inter/generate.py +83 -0
- sierra/plugins/prod/graphs/inter/heatmap.py +86 -0
- sierra/plugins/prod/graphs/inter/line.py +134 -0
- sierra/plugins/prod/graphs/intra/__init__.py +15 -0
- sierra/plugins/prod/graphs/intra/generate.py +202 -0
- sierra/plugins/prod/graphs/intra/heatmap.py +74 -0
- sierra/plugins/prod/graphs/intra/line.py +114 -0
- sierra/plugins/prod/graphs/plugin.py +103 -0
- sierra/plugins/prod/graphs/targets.py +63 -0
- sierra/plugins/prod/render/__init__.py +18 -0
- sierra/plugins/prod/render/cmdline.py +72 -0
- sierra/plugins/prod/render/plugin.py +282 -0
- sierra/plugins/storage/__init__.py +5 -0
- sierra/plugins/storage/arrow/__init__.py +18 -0
- sierra/plugins/storage/arrow/plugin.py +38 -0
- sierra/plugins/storage/csv/__init__.py +9 -0
- sierra/plugins/storage/csv/plugin.py +12 -5
- sierra/version.py +3 -2
- sierra_research-1.5.0.dist-info/METADATA +238 -0
- sierra_research-1.5.0.dist-info/RECORD +186 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/WHEEL +1 -2
- sierra/core/experiment/xml.py +0 -454
- sierra/core/generators/controller_generator_parser.py +0 -34
- sierra/core/generators/exp_creator.py +0 -351
- sierra/core/generators/exp_generators.py +0 -142
- sierra/core/graphs/scatterplot2D.py +0 -109
- sierra/core/graphs/stacked_line_graph.py +0 -249
- sierra/core/graphs/stacked_surface_graph.py +0 -220
- sierra/core/graphs/summary_line_graph.py +0 -369
- sierra/core/hpc/cmdline.py +0 -142
- sierra/core/models/graphs.py +0 -87
- sierra/core/pipeline/stage2/exp_runner.py +0 -286
- sierra/core/pipeline/stage3/imagizer.py +0 -149
- sierra/core/pipeline/stage3/run_collator.py +0 -317
- sierra/core/pipeline/stage3/statistics_calculator.py +0 -478
- sierra/core/pipeline/stage4/graph_collator.py +0 -319
- sierra/core/pipeline/stage4/inter_exp_graph_generator.py +0 -240
- sierra/core/pipeline/stage4/intra_exp_graph_generator.py +0 -317
- sierra/core/pipeline/stage4/model_runner.py +0 -168
- sierra/core/pipeline/stage4/rendering.py +0 -283
- sierra/core/pipeline/stage4/yaml_config_loader.py +0 -103
- sierra/core/pipeline/stage5/inter_scenario_comparator.py +0 -328
- sierra/core/pipeline/stage5/intra_scenario_comparator.py +0 -989
- sierra/core/platform.py +0 -493
- sierra/core/plugin_manager.py +0 -369
- sierra/core/root_dirpath_generator.py +0 -241
- sierra/plugins/hpc/adhoc/plugin.py +0 -125
- sierra/plugins/hpc/local/plugin.py +0 -81
- sierra/plugins/hpc/pbs/__init__.py +0 -9
- sierra/plugins/hpc/pbs/plugin.py +0 -126
- sierra/plugins/hpc/slurm/__init__.py +0 -9
- sierra/plugins/hpc/slurm/plugin.py +0 -130
- sierra/plugins/platform/__init__.py +0 -9
- sierra/plugins/platform/argos/__init__.py +0 -9
- sierra/plugins/platform/argos/generators/platform_generators.py +0 -383
- sierra/plugins/platform/argos/plugin.py +0 -337
- sierra/plugins/platform/argos/variables/arena_shape.py +0 -145
- sierra/plugins/platform/argos/variables/cameras.py +0 -243
- sierra/plugins/platform/argos/variables/constant_density.py +0 -136
- sierra/plugins/platform/argos/variables/exp_setup.py +0 -113
- sierra/plugins/platform/argos/variables/population_constant_density.py +0 -175
- sierra/plugins/platform/argos/variables/population_size.py +0 -102
- sierra/plugins/platform/argos/variables/population_variable_density.py +0 -132
- sierra/plugins/platform/argos/variables/rendering.py +0 -104
- sierra/plugins/platform/ros1gazebo/__init__.py +0 -9
- sierra/plugins/platform/ros1gazebo/cmdline.py +0 -213
- sierra/plugins/platform/ros1gazebo/generators/platform_generators.py +0 -137
- sierra/plugins/platform/ros1gazebo/plugin.py +0 -335
- sierra/plugins/platform/ros1gazebo/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1gazebo/variables/population_size.py +0 -204
- sierra/plugins/platform/ros1robot/__init__.py +0 -9
- sierra/plugins/platform/ros1robot/cmdline.py +0 -175
- sierra/plugins/platform/ros1robot/generators/platform_generators.py +0 -112
- sierra/plugins/platform/ros1robot/plugin.py +0 -373
- sierra/plugins/platform/ros1robot/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1robot/variables/population_size.py +0 -146
- sierra/plugins/robot/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/plugin.py +0 -194
- sierra_research-1.3.6.data/data/share/man/man1/sierra-cli.1 +0 -2349
- sierra_research-1.3.6.data/data/share/man/man7/sierra-examples.7 +0 -488
- sierra_research-1.3.6.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
- sierra_research-1.3.6.data/data/share/man/man7/sierra-glossary.7 +0 -285
- sierra_research-1.3.6.data/data/share/man/man7/sierra-platforms.7 +0 -358
- sierra_research-1.3.6.data/data/share/man/man7/sierra-usage.7 +0 -725
- sierra_research-1.3.6.data/data/share/man/man7/sierra.7 +0 -78
- sierra_research-1.3.6.dist-info/METADATA +0 -500
- sierra_research-1.3.6.dist-info/RECORD +0 -133
- sierra_research-1.3.6.dist-info/top_level.txt +0 -1
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
@@ -10,169 +10,40 @@ import logging
|
|
10
10
|
import argparse
|
11
11
|
import copy
|
12
12
|
import pathlib
|
13
|
+
import itertools
|
13
14
|
|
14
15
|
# 3rd party packages
|
15
16
|
import implements
|
16
17
|
|
18
|
+
# Project packages
|
17
19
|
from sierra.core.variables import base_variable
|
18
20
|
from sierra.core import utils
|
19
|
-
from sierra.core.experiment import definition
|
20
|
-
|
21
|
-
|
22
|
-
import sierra.core.plugin_manager as pm
|
21
|
+
from sierra.core.experiment import definition
|
22
|
+
import sierra.core.plugin as pm
|
23
23
|
from sierra.core import types, config
|
24
|
+
from sierra.core.graphs import bcbridge
|
24
25
|
|
25
26
|
|
26
27
|
class IQueryableBatchCriteria(implements.Interface):
|
27
28
|
"""Mixin interface for criteria which can be queried during stage {1,2}.
|
28
29
|
|
29
30
|
Used to extract additional information needed for configuring some
|
30
|
-
:term:`
|
31
|
-
|
32
|
-
"""
|
33
|
-
|
34
|
-
def n_robots(self, exp_num: int) -> int:
|
35
|
-
"""
|
36
|
-
Return the # of robots used for a given :term:`Experiment`.
|
37
|
-
"""
|
38
|
-
raise NotImplementedError
|
39
|
-
|
40
|
-
|
41
|
-
class IConcreteBatchCriteria(implements.Interface):
|
42
|
-
"""
|
43
|
-
'Final' interface for user-visible batch criteria.
|
44
|
-
"""
|
45
|
-
|
46
|
-
def graph_xticks(self,
|
47
|
-
cmdopts: types.Cmdopts,
|
48
|
-
exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[float]:
|
49
|
-
"""Calculate X axis ticks for graph generation.
|
50
|
-
|
51
|
-
Arguments:
|
52
|
-
|
53
|
-
cmdopts: Dictionary of parsed command line options.
|
54
|
-
|
55
|
-
exp_names: If not None, then this list of directories will be used
|
56
|
-
to calculate the ticks, rather than the results of
|
57
|
-
gen_exp_names().
|
58
|
-
|
59
|
-
"""
|
60
|
-
|
61
|
-
raise NotImplementedError
|
62
|
-
|
63
|
-
def graph_xticklabels(self,
|
64
|
-
cmdopts: types.Cmdopts,
|
65
|
-
exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]:
|
66
|
-
"""Calculate X axis tick labels for graph generation.
|
67
|
-
|
68
|
-
Arguments:
|
69
|
-
|
70
|
-
cmdopts: Dictionary of parsed command line options.
|
71
|
-
|
72
|
-
exp_names: If not None, then these directories will be used to
|
73
|
-
calculate the labels, rather than the results of
|
74
|
-
gen_exp_names().
|
75
|
-
|
76
|
-
"""
|
77
|
-
raise NotImplementedError
|
78
|
-
|
79
|
-
def graph_xlabel(self, cmdopts: types.Cmdopts) -> str:
|
80
|
-
"""Get the X-label for a graph.
|
81
|
-
|
82
|
-
Returns:
|
83
|
-
|
84
|
-
The X-label that should be used for the graphs of various
|
85
|
-
performance measures across batch criteria.
|
86
|
-
|
87
|
-
"""
|
88
|
-
raise NotImplementedError
|
89
|
-
|
90
|
-
|
91
|
-
class IBivarBatchCriteria(implements.Interface):
|
92
|
-
"""
|
93
|
-
Interface for bivariate batch criteria(those with two univariate axes).
|
94
|
-
"""
|
95
|
-
|
96
|
-
def graph_yticks(self,
|
97
|
-
cmdopts: types.Cmdopts,
|
98
|
-
exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[float]:
|
99
|
-
"""
|
100
|
-
Calculate Y axis ticks for graph generation.
|
101
|
-
|
102
|
-
Arguments:
|
103
|
-
|
104
|
-
cmdopts: Dictionary of parsed command line options.
|
105
|
-
|
106
|
-
exp_names: If not None, then these directories will be used to
|
107
|
-
calculate the ticks, rather than the results of
|
108
|
-
gen_exp_names().
|
109
|
-
|
110
|
-
"""
|
111
|
-
raise NotImplementedError
|
112
|
-
|
113
|
-
def graph_yticklabels(self,
|
114
|
-
cmdopts: types.Cmdopts,
|
115
|
-
exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]:
|
116
|
-
"""
|
117
|
-
Calculate X axis ticks for graph generation.
|
118
|
-
|
119
|
-
Arguments:
|
120
|
-
|
121
|
-
cmdopts: Dictionary of parsed command line options.
|
122
|
-
|
123
|
-
exp_names: If not None, then these directories will be used to
|
124
|
-
calculate the labels, rather than the results of
|
125
|
-
gen_exp_names().
|
126
|
-
"""
|
127
|
-
raise NotImplementedError
|
128
|
-
|
129
|
-
def graph_ylabel(self, cmdopts: types.Cmdopts) -> str:
|
130
|
-
"""
|
131
|
-
Get the Y-label for a graph.
|
132
|
-
|
133
|
-
Returns:p
|
134
|
-
|
135
|
-
The Y-label that should be used for the graphs of various
|
136
|
-
performance measures across batch criteria. Only needed by bivar
|
137
|
-
batch criteria.
|
138
|
-
"""
|
139
|
-
raise NotImplementedError
|
140
|
-
|
141
|
-
|
142
|
-
class IBatchCriteriaType(implements.Interface):
|
143
|
-
"""Mixin interface for criteria for querying univariate/bivariate.
|
31
|
+
:term:`Engines <Engine>` and execution environments.
|
144
32
|
|
145
33
|
"""
|
146
34
|
|
147
|
-
def
|
148
|
-
"""
|
149
|
-
Determine if the batch criteria is bivariate.
|
150
|
-
|
151
|
-
Returns:
|
152
|
-
|
153
|
-
`True` if this class is a bivariate batch criteria instance, and
|
154
|
-
`False` otherwise.
|
155
|
-
"""
|
156
|
-
raise NotImplementedError
|
157
|
-
|
158
|
-
def is_univar(self) -> bool:
|
35
|
+
def n_agents(self, exp_num: int) -> int:
|
159
36
|
"""
|
160
|
-
|
161
|
-
|
162
|
-
Returns:
|
163
|
-
|
164
|
-
`True` if this class is a univar batch criteria instance, and
|
165
|
-
`False` otherwise.
|
37
|
+
Return the # of agents used for a given :term:`Experiment`.
|
166
38
|
"""
|
167
39
|
raise NotImplementedError
|
168
40
|
|
169
41
|
|
170
42
|
@implements.implements(base_variable.IBaseVariable)
|
171
|
-
class
|
172
|
-
"""Defines experiments via lists of sets of changes to make to an
|
43
|
+
class BaseBatchCriteria:
|
44
|
+
"""Defines experiments via lists of sets of changes to make to an expdef.
|
173
45
|
|
174
46
|
Attributes:
|
175
|
-
|
176
47
|
cli_arg: Unparsed batch criteria string from command line.
|
177
48
|
|
178
49
|
main_config: Parsed dictionary of main YAML configuration.
|
@@ -182,72 +53,72 @@ class BatchCriteria():
|
|
182
53
|
|
183
54
|
"""
|
184
55
|
|
185
|
-
def __init__(
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
56
|
+
def __init__(
|
57
|
+
self, cli_arg: str, main_config: types.YAMLDict, batch_input_root: pathlib.Path
|
58
|
+
) -> None:
|
59
|
+
|
60
|
+
# 2025-09-21 [JRH]: The "name" of the batch criteria is just whatever is
|
61
|
+
# passed on the cmdline.
|
62
|
+
self.name = cli_arg
|
190
63
|
self.main_config = main_config
|
191
64
|
self.batch_input_root = batch_input_root
|
192
65
|
|
193
|
-
self.cat_str = cli_arg.split(
|
194
|
-
self.def_str =
|
66
|
+
self.cat_str = cli_arg.split(".")[0]
|
67
|
+
self.def_str = ".".join(cli_arg.split(".")[1:])
|
195
68
|
self.logger = logging.getLogger(__name__)
|
196
69
|
|
197
70
|
# Stub out IBaseVariable because all concrete batch criteria only implement
|
198
71
|
# a subset of them.
|
199
|
-
def gen_attr_changelist(self) -> tp.List[
|
72
|
+
def gen_attr_changelist(self) -> tp.List[definition.AttrChangeSet]:
|
200
73
|
return []
|
201
74
|
|
202
|
-
def gen_tag_rmlist(self) -> tp.List[
|
75
|
+
def gen_tag_rmlist(self) -> tp.List[definition.ElementRmList]:
|
203
76
|
return []
|
204
77
|
|
205
|
-
def
|
78
|
+
def gen_element_addlist(self) -> tp.List[definition.ElementAddList]:
|
206
79
|
return []
|
207
80
|
|
208
81
|
def gen_files(self) -> None:
|
209
82
|
pass
|
210
83
|
|
211
|
-
def
|
212
|
-
|
213
|
-
Generate list of experiment names from the criteria.
|
214
|
-
|
215
|
-
Used for creating unique directory names for each experiment in the
|
216
|
-
batch.
|
84
|
+
def cardinality(self) -> int:
|
85
|
+
return -1
|
217
86
|
|
218
|
-
|
219
|
-
|
220
|
-
List of experiments names for current experiment.
|
87
|
+
def gen_exp_names(self) -> tp.List[str]:
|
88
|
+
raise NotImplementedError
|
221
89
|
|
222
|
-
|
223
|
-
return
|
90
|
+
def computable_exp_scenario_name(self) -> bool:
|
91
|
+
return False
|
224
92
|
|
225
93
|
def arena_dims(self, cmdopts: types.Cmdopts) -> tp.List[utils.ArenaExtent]:
|
226
94
|
"""Get the arena dimensions used for each experiment in the batch.
|
227
95
|
|
228
96
|
Not applicable to all criteria.
|
229
97
|
|
230
|
-
Must be implemented on a per-
|
98
|
+
Must be implemented on a per-engine basis, as different engines have
|
231
99
|
different means of computing the size of the arena.
|
232
100
|
|
233
101
|
"""
|
234
|
-
module = pm.pipeline.get_plugin_module(cmdopts[
|
235
|
-
assert hasattr(
|
236
|
-
|
102
|
+
module = pm.pipeline.get_plugin_module(cmdopts["engine"])
|
103
|
+
assert hasattr(
|
104
|
+
module, "arena_dims_from_criteria"
|
105
|
+
), f"Engine plugin {module.__name__} does not implement arena_dims_from_criteria()"
|
237
106
|
|
238
107
|
return module.arena_dims_from_criteria(self)
|
239
108
|
|
240
109
|
def n_exp(self) -> int:
|
241
110
|
from sierra.core.experiment import spec
|
111
|
+
|
242
112
|
scaffold_spec = spec.scaffold_spec_factory(self)
|
243
113
|
return scaffold_spec.n_exps
|
244
114
|
|
245
115
|
def pickle_exp_defs(self, cmdopts: types.Cmdopts) -> None:
|
246
116
|
from sierra.core.experiment import spec
|
117
|
+
|
247
118
|
scaffold_spec = spec.scaffold_spec_factory(self)
|
248
119
|
|
249
120
|
for exp in range(0, scaffold_spec.n_exps):
|
250
|
-
exp_dirname = self.gen_exp_names(
|
121
|
+
exp_dirname = self.gen_exp_names()[exp]
|
251
122
|
# Pickling of batch criteria experiment definitions is the FIRST set
|
252
123
|
# of changes to be pickled--all other changes come after. We append
|
253
124
|
# to the pickle file by default, which allows any number of
|
@@ -264,128 +135,127 @@ class BatchCriteria():
|
|
264
135
|
exp_defi[0].pickle(pkl_path, delete=True)
|
265
136
|
exp_defi[1].pickle(pkl_path, delete=False)
|
266
137
|
|
267
|
-
def scaffold_exps(
|
268
|
-
|
269
|
-
|
138
|
+
def scaffold_exps(
|
139
|
+
self, batch_def: definition.BaseExpDef, cmdopts: types.Cmdopts
|
140
|
+
) -> None:
|
270
141
|
"""Scaffold a batch experiment.
|
271
142
|
|
272
|
-
Takes the raw template input file and apply
|
143
|
+
Takes the raw template input file and apply expdef modifications from the
|
273
144
|
batch criteria for all experiments, and save the result in each
|
274
145
|
experiment's input directory.
|
275
146
|
|
276
147
|
"""
|
277
148
|
|
278
149
|
from sierra.core.experiment import spec
|
150
|
+
|
279
151
|
scaffold_spec = spec.scaffold_spec_factory(self, log=True)
|
280
152
|
|
281
153
|
for i in range(0, scaffold_spec.n_exps):
|
282
154
|
modsi = scaffold_spec.mods[i]
|
283
155
|
expi_def = copy.deepcopy(batch_def)
|
284
|
-
self._scaffold_expi(expi_def,
|
285
|
-
modsi,
|
286
|
-
scaffold_spec.is_compound,
|
287
|
-
i,
|
288
|
-
cmdopts)
|
156
|
+
self._scaffold_expi(expi_def, modsi, scaffold_spec.is_compound, i, cmdopts)
|
289
157
|
|
290
158
|
n_exp_dirs = len(list(self.batch_input_root.iterdir()))
|
291
159
|
if scaffold_spec.n_exps != n_exp_dirs:
|
292
|
-
msg1 = (
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
160
|
+
msg1 = (
|
161
|
+
f"Size of batch experiment ({scaffold_spec.n_exps}) != "
|
162
|
+
f"# exp dirs ({n_exp_dirs}): possibly caused by:"
|
163
|
+
)
|
164
|
+
msg2 = (
|
165
|
+
f"(1) Changing bc w/o changing the generation root "
|
166
|
+
f"({self.batch_input_root})"
|
167
|
+
)
|
168
|
+
msg3 = (
|
169
|
+
f"(2) Sharing {self.batch_input_root} between different "
|
170
|
+
f"batch criteria"
|
171
|
+
)
|
298
172
|
|
299
173
|
self.logger.fatal(msg1)
|
300
174
|
self.logger.fatal(msg2)
|
301
175
|
self.logger.fatal(msg3)
|
302
176
|
raise RuntimeError("Batch experiment size/# exp dir mismatch")
|
303
177
|
|
304
|
-
def _scaffold_expi(
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
178
|
+
def _scaffold_expi(
|
179
|
+
self,
|
180
|
+
expi_def: definition.BaseExpDef,
|
181
|
+
modsi,
|
182
|
+
is_compound: bool,
|
183
|
+
i: int,
|
184
|
+
cmdopts: types.Cmdopts,
|
185
|
+
) -> None:
|
186
|
+
|
187
|
+
exp_dirname = self.gen_exp_names()[i]
|
311
188
|
exp_input_root = self.batch_input_root / exp_dirname
|
312
189
|
|
313
|
-
utils.dir_create_checked(exp_input_root,
|
314
|
-
exist_ok=cmdopts['exp_overwrite'])
|
190
|
+
utils.dir_create_checked(exp_input_root, exist_ok=cmdopts["exp_overwrite"])
|
315
191
|
|
316
192
|
if not is_compound:
|
317
|
-
self.logger.debug(
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
193
|
+
self.logger.debug(
|
194
|
+
("Applying %s expdef mods from '%s' for exp%s in %s"),
|
195
|
+
len(modsi),
|
196
|
+
self.name,
|
197
|
+
i,
|
198
|
+
exp_dirname,
|
199
|
+
)
|
323
200
|
|
324
201
|
for mod in modsi:
|
325
|
-
if isinstance(mod,
|
202
|
+
if isinstance(mod, definition.AttrChange):
|
326
203
|
expi_def.attr_change(mod.path, mod.attr, mod.value)
|
327
|
-
elif isinstance(mod,
|
328
|
-
assert
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
mod.attr,
|
333
|
-
mod.allow_dup)
|
204
|
+
elif isinstance(mod, definition.ElementAdd):
|
205
|
+
assert (
|
206
|
+
mod.path is not None
|
207
|
+
), "Cannot add root {mode.tag} during scaffolding"
|
208
|
+
expi_def.element_add(mod.path, mod.tag, mod.attr, mod.allow_dup)
|
334
209
|
else:
|
335
|
-
self.logger.debug(
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
210
|
+
self.logger.debug(
|
211
|
+
("Applying %s expdef modifications from '%s' for exp%s in %s"),
|
212
|
+
len(modsi[0]) + len(modsi[1]),
|
213
|
+
self.name,
|
214
|
+
i,
|
215
|
+
exp_dirname,
|
216
|
+
)
|
341
217
|
|
342
218
|
# Mods are a tuple for compound specs: adds, changes. We do adds
|
343
219
|
# first, in case some insane person wants to use the second batch
|
344
220
|
# criteria to modify something they just added.
|
345
221
|
for add in modsi[0]:
|
346
|
-
expi_def.
|
347
|
-
add.tag,
|
348
|
-
add.attr,
|
349
|
-
add.allow_dup)
|
222
|
+
expi_def.element_add(add.path, add.tag, add.attr, add.allow_dup)
|
350
223
|
for chg in modsi[1]:
|
351
|
-
expi_def.attr_change(chg.path,
|
352
|
-
chg.attr,
|
353
|
-
chg.value)
|
224
|
+
expi_def.attr_change(chg.path, chg.attr, chg.value)
|
354
225
|
|
355
226
|
# This will be the "template" input file used to generate the input
|
356
227
|
# files for each experimental run in the experiment
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
228
|
+
fmt = pm.pipeline.get_plugin_module(cmdopts["expdef"])
|
229
|
+
wr_config = definition.WriterConfig(
|
230
|
+
[
|
231
|
+
{
|
232
|
+
"src_parent": None,
|
233
|
+
"src_tag": fmt.root_querypath(),
|
234
|
+
"opath_leaf": None,
|
235
|
+
"new_children": None,
|
236
|
+
"new_children_parent": None,
|
237
|
+
}
|
238
|
+
]
|
239
|
+
)
|
363
240
|
expi_def.write_config_set(wr_config)
|
364
|
-
opath = utils.exp_template_path(cmdopts,
|
365
|
-
self.batch_input_root,
|
366
|
-
exp_dirname)
|
241
|
+
opath = utils.exp_template_path(cmdopts, self.batch_input_root, exp_dirname)
|
367
242
|
expi_def.write(opath)
|
368
243
|
|
369
244
|
|
370
|
-
|
371
|
-
class UnivarBatchCriteria(BatchCriteria):
|
245
|
+
class UnivarBatchCriteria(BaseBatchCriteria):
|
372
246
|
"""
|
373
247
|
Base class for a univariate batch criteria.
|
374
248
|
"""
|
375
249
|
|
376
|
-
|
377
|
-
|
378
|
-
#
|
379
|
-
|
380
|
-
def is_bivar(self) -> bool:
|
381
|
-
return False
|
250
|
+
def cardinality(self) -> int:
|
251
|
+
return 1
|
382
252
|
|
383
|
-
def
|
384
|
-
return
|
253
|
+
def gen_exp_names(self) -> tp.List[str]:
|
254
|
+
return [f"c1-exp{i}" for i in range(0, self.n_exp())]
|
385
255
|
|
386
|
-
def populations(
|
387
|
-
|
388
|
-
|
256
|
+
def populations(
|
257
|
+
self, cmdopts: types.Cmdopts, exp_names: tp.Optional[tp.List[str]] = None
|
258
|
+
) -> tp.List[int]:
|
389
259
|
"""
|
390
260
|
Calculate system sizes used the batch experiment, sorted.
|
391
261
|
|
@@ -402,142 +272,198 @@ class UnivarBatchCriteria(BatchCriteria):
|
|
402
272
|
if exp_names is not None:
|
403
273
|
names = exp_names
|
404
274
|
else:
|
405
|
-
names = self.gen_exp_names(
|
275
|
+
names = self.gen_exp_names()
|
406
276
|
|
407
|
-
|
277
|
+
module1 = pm.pipeline.get_plugin_module(cmdopts["engine"])
|
278
|
+
module2 = pm.pipeline.get_plugin_module(cmdopts["expdef"])
|
408
279
|
for d in names:
|
409
280
|
path = self.batch_input_root / d / config.kPickleLeaf
|
410
|
-
exp_def =
|
281
|
+
exp_def = module2.unpickle(path)
|
282
|
+
|
283
|
+
sizes.append(
|
284
|
+
module1.population_size_from_pickle(exp_def, self.main_config, cmdopts)
|
285
|
+
)
|
411
286
|
|
412
|
-
sizes.append(module.population_size_from_pickle(exp_def,
|
413
|
-
self.main_config,
|
414
|
-
cmdopts))
|
415
287
|
return sizes
|
416
288
|
|
417
289
|
|
418
|
-
@implements.implements(
|
419
|
-
@implements.implements(IBatchCriteriaType)
|
290
|
+
@implements.implements(bcbridge.IGraphable)
|
420
291
|
@implements.implements(IQueryableBatchCriteria)
|
421
|
-
class
|
292
|
+
class XVarBatchCriteria(BaseBatchCriteria):
|
422
293
|
"""
|
423
|
-
|
294
|
+
N-dimensional multiple :class:`sierra.core.variables.batch_criteria.UnivarBatchCriteria`.
|
424
295
|
|
425
296
|
.. versionchanged:: 1.2.20
|
426
297
|
|
427
|
-
|
428
|
-
|
429
|
-
|
298
|
+
Batch criteria can be compound: one criteria can create and the other
|
299
|
+
modify expdef elements to create an experiment definition.
|
430
300
|
"""
|
431
301
|
|
432
|
-
def __init__(self,
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
self.
|
440
|
-
self.criteria2 = criteria2
|
441
|
-
#
|
442
|
-
# IBatchCriteriaType overrides
|
443
|
-
#
|
444
|
-
|
445
|
-
def is_bivar(self) -> bool:
|
446
|
-
return True
|
447
|
-
|
448
|
-
def is_univar(self) -> bool:
|
449
|
-
return False
|
302
|
+
def __init__(self, criterias: tp.List[BaseBatchCriteria]) -> None:
|
303
|
+
BaseBatchCriteria.__init__(
|
304
|
+
self,
|
305
|
+
"+".join([c.name for c in criterias]),
|
306
|
+
criterias[0].main_config,
|
307
|
+
criterias[0].batch_input_root,
|
308
|
+
)
|
309
|
+
self.criterias = criterias
|
450
310
|
|
451
|
-
def
|
452
|
-
|
453
|
-
list2 = self.criteria2.gen_attr_changelist()
|
454
|
-
ret = []
|
311
|
+
def cardinality(self) -> int:
|
312
|
+
return len(self.criterias)
|
455
313
|
|
456
|
-
|
457
|
-
|
458
|
-
for l2 in list2:
|
459
|
-
ret.append(l1 | l2)
|
314
|
+
def computable_exp_scenario_name(self) -> bool:
|
315
|
+
return any(c.computable_exp_scenario_name() for c in self.criterias)
|
460
316
|
|
461
|
-
|
462
|
-
|
317
|
+
def gen_attr_changelist(self) -> tp.List[definition.AttrChangeSet]:
|
318
|
+
changes = [c.gen_attr_changelist() for c in self.criterias]
|
463
319
|
|
464
|
-
|
465
|
-
|
320
|
+
# Flatten each list of sets into a single list of items
|
321
|
+
flattened_lists = []
|
466
322
|
|
467
|
-
|
323
|
+
for list_of_sets in changes:
|
324
|
+
flattened_list = [] # type: tp.List[definition.AttrChangeSet]
|
325
|
+
for s in list_of_sets:
|
326
|
+
flattened_list.append(s)
|
468
327
|
|
469
|
-
|
470
|
-
list1 = self.criteria1.gen_tag_addlist()
|
471
|
-
list2 = self.criteria2.gen_tag_addlist()
|
472
|
-
ret = []
|
328
|
+
flattened_lists.append(flattened_list)
|
473
329
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
330
|
+
# Use itertools.product to get all combinations
|
331
|
+
result = []
|
332
|
+
for combination in itertools.product(*flattened_lists):
|
333
|
+
combined = definition.AttrChangeSet()
|
334
|
+
# Add all changes from each AttrChangeSet in the combination
|
335
|
+
for change_set in combination:
|
336
|
+
for change in change_set:
|
337
|
+
combined.add(change)
|
481
338
|
|
482
|
-
|
483
|
-
ret = list2
|
339
|
+
result.append(combined)
|
484
340
|
|
485
|
-
return
|
341
|
+
return result
|
486
342
|
|
487
|
-
def
|
488
|
-
|
489
|
-
|
490
|
-
|
343
|
+
def gen_element_addlist(self) -> tp.List[definition.ElementAddList]:
|
344
|
+
adds = [c.gen_element_addlist() for c in self.criterias]
|
345
|
+
|
346
|
+
# Create combinations and combine ElementAddList objects
|
347
|
+
result = []
|
348
|
+
for combo in itertools.product(*adds):
|
349
|
+
combined = definition.ElementAddList()
|
350
|
+
|
351
|
+
# Add all ElementAdd objects from each ElementAddList in the combo
|
352
|
+
for elem_add_list in combo:
|
353
|
+
for elem_add in elem_add_list:
|
354
|
+
combined.append(elem_add)
|
355
|
+
|
356
|
+
result.append(combined)
|
357
|
+
|
358
|
+
return result
|
359
|
+
|
360
|
+
def gen_tag_rmlist(self) -> tp.List[definition.ElementRmList]:
|
361
|
+
rms = [c.gen_tag_rmlist() for c in self.criterias]
|
491
362
|
|
492
|
-
|
363
|
+
# Create combinations and combine ElementRmList objects
|
364
|
+
result = []
|
365
|
+
for combo in itertools.product(*rms):
|
366
|
+
combined = definition.ElementRmList()
|
367
|
+
|
368
|
+
# Add all ElementRm objects from each ElementRmList in the combo
|
369
|
+
for elem_rm_list in combo:
|
370
|
+
for elem_rm in elem_rm_list:
|
371
|
+
combined.append(elem_rm)
|
372
|
+
result.append(combined)
|
373
|
+
|
374
|
+
return result
|
375
|
+
|
376
|
+
def gen_exp_names(self) -> tp.List[str]:
|
493
377
|
"""
|
494
378
|
Generate a SORTED list of strings for all experiment names.
|
495
379
|
|
496
|
-
These will be used as directory LEAF names
|
497
|
-
parents.
|
380
|
+
These will be used as directory LEAF names, and don't include the
|
381
|
+
parents. Basically, this is a flattened list of permutations of all
|
382
|
+
``gen_exp_names()`` for each batch criteria.
|
498
383
|
|
499
384
|
"""
|
500
|
-
list1 = self.criteria1.gen_exp_names(cmdopts)
|
501
|
-
list2 = self.criteria2.gen_exp_names(cmdopts)
|
502
|
-
ret = []
|
503
385
|
|
504
|
-
|
505
|
-
|
506
|
-
|
386
|
+
# Collect all criteria lists with their prefixes
|
387
|
+
criteria_lists = []
|
388
|
+
for i, criteria in enumerate(self.criterias, 1):
|
389
|
+
prefixed_names = [f"c{i}-exp{j}" for j in range(0, criteria.n_exp())]
|
390
|
+
criteria_lists.append(prefixed_names)
|
391
|
+
|
392
|
+
# Generate all combinations using itertools.product
|
393
|
+
ret = []
|
394
|
+
for combination in itertools.product(*criteria_lists):
|
395
|
+
ret.append("+".join(combination))
|
507
396
|
|
508
397
|
return ret
|
509
398
|
|
510
|
-
def populations(self, cmdopts: types.Cmdopts) ->
|
511
|
-
"""Generate a
|
399
|
+
def populations(self, cmdopts: types.Cmdopts) -> list:
|
400
|
+
"""Generate a N-D array of system sizes used the batch experiment.
|
512
401
|
|
513
402
|
Sizes are in the same order as the directories returned from
|
514
|
-
|
403
|
+
``gen_exp_names()`` for each criteria along each axis.
|
515
404
|
|
516
405
|
"""
|
517
|
-
names = self.gen_exp_names(
|
406
|
+
names = self.gen_exp_names()
|
407
|
+
criteria_dims = []
|
408
|
+
criteria_counts = []
|
409
|
+
|
410
|
+
for criteria in self.criterias:
|
411
|
+
exp_names = criteria.gen_exp_names()
|
412
|
+
n_chgs = len(criteria.gen_attr_changelist())
|
413
|
+
n_adds = len(criteria.gen_element_addlist())
|
414
|
+
|
415
|
+
criteria_dims.append(len(exp_names))
|
416
|
+
criteria_counts.append(n_chgs + n_adds)
|
518
417
|
|
519
|
-
|
520
|
-
|
418
|
+
# Create multi-dimensional nested list initialized with zeros
|
419
|
+
def create_nested_list(dimensions: tp.List[int]) -> list:
|
420
|
+
if len(dimensions) == 1:
|
421
|
+
return [0] * dimensions[0]
|
422
|
+
return [create_nested_list(dimensions[1:]) for _ in range(dimensions[0])]
|
521
423
|
|
522
|
-
|
523
|
-
|
424
|
+
sizes = create_nested_list(criteria_dims)
|
425
|
+
|
426
|
+
# Get plugin modules
|
427
|
+
module1 = pm.pipeline.get_plugin_module(cmdopts["engine"])
|
428
|
+
module2 = pm.pipeline.get_plugin_module(cmdopts["expdef"])
|
429
|
+
|
430
|
+
# Calculate total combinations for index conversion
|
431
|
+
total_combinations = 1
|
432
|
+
for count in criteria_counts:
|
433
|
+
total_combinations *= count
|
524
434
|
|
525
|
-
module = pm.pipeline.get_plugin_module(cmdopts['platform'])
|
526
435
|
for d in names:
|
527
436
|
pkl_path = self.batch_input_root / d / config.kPickleLeaf
|
528
|
-
exp_def =
|
437
|
+
exp_def = module2.unpickle(pkl_path)
|
529
438
|
|
439
|
+
# Convert linear index to multi-dimensional indices
|
530
440
|
index = names.index(d)
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
441
|
+
indices = []
|
442
|
+
remaining_index = index
|
443
|
+
|
444
|
+
for i in range(len(criteria_counts)):
|
445
|
+
# Calculate stride for this dimension
|
446
|
+
stride = 1
|
447
|
+
for j in range(i + 1, len(criteria_counts)):
|
448
|
+
stride *= criteria_counts[j]
|
449
|
+
|
450
|
+
# Calculate index for this dimension
|
451
|
+
dim_index = remaining_index // stride
|
452
|
+
indices.append(dim_index)
|
453
|
+
remaining_index = remaining_index % stride
|
454
|
+
|
455
|
+
# Set the population size at the calculated indices
|
456
|
+
current_level = sizes
|
457
|
+
for i, idx in enumerate(indices[:-1]):
|
458
|
+
current_level = current_level[idx]
|
459
|
+
current_level[indices[-1]] = module1.population_size_from_pickle(
|
460
|
+
exp_def, self.main_config, cmdopts
|
461
|
+
)
|
536
462
|
|
537
463
|
return sizes
|
538
464
|
|
539
465
|
def exp_scenario_name(self, exp_num: int) -> str:
|
540
|
-
"""Given the
|
466
|
+
"""Given the experiment number, compute a parsable scenario name.
|
541
467
|
|
542
468
|
It is necessary to query this function after generating the changelist
|
543
469
|
in order to create generator classes for each experiment in the batch
|
@@ -546,181 +472,161 @@ class BivarBatchCriteria(BatchCriteria):
|
|
546
472
|
Can only be called if constant density is one of the sub-criteria.
|
547
473
|
|
548
474
|
"""
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
def
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
return self.criteria1.graph_xticklabels(cmdopts, names)
|
608
|
-
|
609
|
-
def graph_yticklabels(self,
|
610
|
-
cmdopts: types.Cmdopts,
|
611
|
-
exp_names: tp.Optional[tp.List[str]] = None) -> tp.List[str]:
|
612
|
-
names = []
|
613
|
-
all_dirs = utils.exp_range_calc(cmdopts,
|
614
|
-
cmdopts['batch_output_root'],
|
615
|
-
self)
|
616
|
-
|
617
|
-
for c2 in self.criteria2.gen_exp_names(cmdopts):
|
618
|
-
for y in all_dirs:
|
619
|
-
leaf = y.name
|
620
|
-
if c2 in leaf.split('+')[1]:
|
621
|
-
names.append(leaf)
|
622
|
-
break
|
623
|
-
|
624
|
-
return self.criteria2.graph_xticklabels(cmdopts, names)
|
625
|
-
|
626
|
-
def graph_xlabel(self, cmdopts: types.Cmdopts) -> str:
|
627
|
-
return self.criteria1.graph_xlabel(cmdopts)
|
628
|
-
|
629
|
-
def graph_ylabel(self, cmdopts: types.Cmdopts) -> str:
|
630
|
-
return self.criteria2.graph_xlabel(cmdopts)
|
475
|
+
for criteria in self.criterias:
|
476
|
+
if hasattr(criteria, "exp_scenario_name"):
|
477
|
+
return criteria.exp_scenario_name(
|
478
|
+
int(exp_num / len(criteria.gen_attr_changelist()))
|
479
|
+
)
|
480
|
+
raise RuntimeError(
|
481
|
+
"Batch criteria does not define 'exp_scenario_name()' required for constant density scenarios"
|
482
|
+
)
|
483
|
+
|
484
|
+
def graph_info(
|
485
|
+
self,
|
486
|
+
cmdopts: types.Cmdopts,
|
487
|
+
batch_output_root: tp.Optional[pathlib.Path] = None,
|
488
|
+
exp_names: tp.Optional[tp.List[str]] = None,
|
489
|
+
) -> bcbridge.GraphInfo:
|
490
|
+
info = bcbridge.GraphInfo(
|
491
|
+
cmdopts,
|
492
|
+
batch_output_root,
|
493
|
+
self.gen_exp_names(),
|
494
|
+
)
|
495
|
+
|
496
|
+
# 2025-07-08 [JRH]: Eventually, this will be replaced with axes
|
497
|
+
# selection, but for now, limiting to bivariate is the simpler way to
|
498
|
+
# go.
|
499
|
+
assert (
|
500
|
+
len(self.criterias) <= 2
|
501
|
+
), "Only {univar,bivar} batch criteria graph generation currently supported"
|
502
|
+
|
503
|
+
exp_names = self.gen_exp_names()
|
504
|
+
if self.cardinality() == 1:
|
505
|
+
info1 = self.criterias[0].graph_info(
|
506
|
+
cmdopts, exp_names=exp_names, batch_output_root=batch_output_root
|
507
|
+
)
|
508
|
+
|
509
|
+
info.xticks = info1.xticks
|
510
|
+
info.xlabel = info1.xlabel
|
511
|
+
info.xticklabels = [str(x) for x in info.xticks]
|
512
|
+
|
513
|
+
elif self.cardinality() == 2:
|
514
|
+
c1_xnames = [f"c1-exp{i}" for i in range(0, self.criterias[0].n_exp())]
|
515
|
+
xnames = [d for d in self.gen_exp_names() if any(x in d for x in c1_xnames)]
|
516
|
+
c2_ynames = [f"c1-exp{i}" for i in range(0, self.criterias[1].n_exp())]
|
517
|
+
ynames = [d for d in self.gen_exp_names() if any(y in d for y in c2_ynames)]
|
518
|
+
|
519
|
+
info1 = self.criterias[0].graph_info(
|
520
|
+
cmdopts, exp_names=xnames, batch_output_root=batch_output_root
|
521
|
+
)
|
522
|
+
info2 = self.criterias[1].graph_info(
|
523
|
+
cmdopts, exp_names=ynames, batch_output_root=batch_output_root
|
524
|
+
)
|
525
|
+
info.xticks = info1.xticks
|
526
|
+
info.xticklabels = [str(x) for x in info.xticks]
|
527
|
+
info.yticks = info2.xticks
|
528
|
+
info.xlabel = info1.xlabel
|
529
|
+
info.ylabel = info2.xlabel
|
530
|
+
info.yticklabels = [str(x) for x in info.yticks]
|
531
|
+
|
532
|
+
return info
|
631
533
|
|
632
534
|
def set_batch_input_root(self, root: pathlib.Path) -> None:
|
633
535
|
self.batch_input_root = root
|
634
|
-
self.
|
635
|
-
|
636
|
-
|
637
|
-
def
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
cmdopts: types.Cmdopts,
|
677
|
-
cli_arg: str,
|
678
|
-
scenario) -> IConcreteBatchCriteria:
|
536
|
+
for criteria in self.criterias:
|
537
|
+
criteria.batch_input_root = root
|
538
|
+
|
539
|
+
def n_agents(self, exp_num: int) -> int:
|
540
|
+
# Calculate dimensions and counts for each criteria
|
541
|
+
criteria_counts = []
|
542
|
+
for criteria in self.criterias:
|
543
|
+
n_chgs = len(criteria.gen_attr_changelist())
|
544
|
+
n_adds = len(criteria.gen_element_addlist())
|
545
|
+
criteria_counts.append(n_chgs + n_adds)
|
546
|
+
|
547
|
+
# Convert linear experiment number to multi-dimensional indices
|
548
|
+
indices = []
|
549
|
+
remaining_exp_num = exp_num
|
550
|
+
|
551
|
+
for i in range(len(criteria_counts)):
|
552
|
+
# Calculate stride for this dimension
|
553
|
+
stride = 1
|
554
|
+
for j in range(i + 1, len(criteria_counts)):
|
555
|
+
stride *= criteria_counts[j]
|
556
|
+
|
557
|
+
# Calculate index for this dimension
|
558
|
+
dim_index = remaining_exp_num // stride
|
559
|
+
indices.append(dim_index)
|
560
|
+
remaining_exp_num = remaining_exp_num % stride
|
561
|
+
|
562
|
+
# Find the first criteria that has an n_agents method and use it
|
563
|
+
for i, criteria in enumerate(self.criteria):
|
564
|
+
if hasattr(criteria, "n_agents"):
|
565
|
+
return criteria.n_agents(indices[i])
|
566
|
+
|
567
|
+
# If no criteria has n_agents method, raise an error
|
568
|
+
raise AttributeError("No criteria has an 'n_agents' method")
|
569
|
+
|
570
|
+
|
571
|
+
def univar_factory(
|
572
|
+
main_config: types.YAMLDict,
|
573
|
+
cmdopts: types.Cmdopts,
|
574
|
+
batch_input_root: pathlib.Path,
|
575
|
+
cli_arg: str,
|
576
|
+
scenario,
|
577
|
+
) -> BaseBatchCriteria:
|
679
578
|
"""
|
680
|
-
Construct a batch criteria object from a single cmdline argument.
|
579
|
+
Construct a univariate batch criteria object from a single cmdline argument.
|
681
580
|
"""
|
682
|
-
category = cli_arg.split(
|
683
|
-
path = f
|
581
|
+
category = cli_arg.split(".")[0]
|
582
|
+
path = f"variables.{category}"
|
684
583
|
|
685
584
|
module = pm.bc_load(cmdopts, category)
|
686
585
|
bcfactory = getattr(module, "factory")
|
687
586
|
|
688
|
-
if 5 in cmdopts[
|
689
|
-
ret = bcfactory(
|
690
|
-
|
691
|
-
|
692
|
-
scenario=scenario)()
|
587
|
+
if 5 in cmdopts["pipeline"]:
|
588
|
+
ret = bcfactory(
|
589
|
+
cli_arg, main_config, cmdopts, batch_input_root, scenario=scenario
|
590
|
+
)
|
693
591
|
else:
|
694
|
-
ret = bcfactory(cli_arg, main_config, cmdopts)
|
592
|
+
ret = bcfactory(cli_arg, main_config, cmdopts, batch_input_root)
|
695
593
|
|
696
|
-
logging.info("Create univariate batch criteria
|
697
|
-
ret.__class__.__name__,
|
698
|
-
path)
|
594
|
+
logging.info("Create univariate batch criteria %s from %s", ret.name, path)
|
699
595
|
return ret # type: ignore
|
700
596
|
|
701
597
|
|
702
|
-
def
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
598
|
+
def factory(
|
599
|
+
main_config: types.YAMLDict,
|
600
|
+
cmdopts: types.Cmdopts,
|
601
|
+
batch_input_root: pathlib.Path,
|
602
|
+
args: argparse.Namespace,
|
603
|
+
scenario: tp.Optional[str] = None,
|
604
|
+
) -> BaseBatchCriteria:
|
605
|
+
"""
|
606
|
+
Construct a multivariate batch criteria object from cmdline input.
|
607
|
+
"""
|
608
|
+
criterias = [
|
609
|
+
univar_factory(main_config, cmdopts, batch_input_root, arg, scenario)
|
610
|
+
for arg in args.batch_criteria
|
611
|
+
]
|
708
612
|
|
709
613
|
# Project hook
|
710
|
-
bc = pm.module_load_tiered(
|
711
|
-
|
712
|
-
|
614
|
+
bc = pm.module_load_tiered(
|
615
|
+
project=cmdopts["project"], path="variables.batch_criteria"
|
616
|
+
)
|
617
|
+
ret = bc.XVarBatchCriteria(criterias)
|
713
618
|
|
714
|
-
logging.info(
|
715
|
-
|
716
|
-
|
619
|
+
logging.info(
|
620
|
+
"Created %s-D batch criteria from %s",
|
621
|
+
len(criterias),
|
622
|
+
",".join([c.name for c in criterias]),
|
623
|
+
)
|
717
624
|
|
718
625
|
return ret # type: ignore
|
719
626
|
|
720
627
|
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
'BivarBatchCriteria',
|
628
|
+
__all__ = [
|
629
|
+
"BaseBatchCriteria",
|
630
|
+
"UnivarBatchCriteria",
|
631
|
+
"XVarBatchCriteria",
|
726
632
|
]
|