# Copyright 2018 London Lowmanstone, John Harwell, All rights reserved.
#
# SPDX-License-Identifier: MIT
"""Experiment generation classes.
Experiment generation modifies the
:class:`~sierra.core.experiment.definition.XMLExpDef` object built from
the specified batch criteria as follows:
- Platform-specific modifications common to all batch experiments
- Project-specific modifications common to all batch experiments
- Modifications generated by the selected controller+scenario
NOTE:: Generated definitions from batch criteria are not handled here; they are
already generated to scaffold the batch experiment when experiment
generation is run.
"""
# Core packages
import typing as tp
import logging
import pathlib
# 3rd party packages
# Project packages
import sierra.core.generators.generator_factory as gf
from sierra.core.experiment import spec, definition
from sierra.core import types
import sierra.core.variables.batch_criteria as bc
[docs]class BatchExpDefGenerator:
"""Generate experiment definitions for a :term:`Batch Experiment`.
Does not create the batch experiment after generation.
Attributes:
batch_config_template: Absolute path to the root template XML
configuration file.
batch_input_root: Root directory for all generated XML input files all
experiments should be stored (relative to current
dir or absolute). Each experiment will get a
directory within this root to store the xml input
files for the set of :term:`Experimental Runs
<Experimental Run>` comprising an
:term:`Experiment`; directory name determined by
the batch criteria used.
batch_output_root: Root directory for all experiment outputs (relative
to current dir or absolute). Each experiment will get
a directory 'exp<n>' in this directory for its
outputs.
criteria: :class:`~sierra.core.variables.batch_criteria.BatchCriteria`
derived object instance created from cmdline definition.
controller_name: Name of controller generator to use.
scenario_basename: Name of scenario generator to use.
"""
[docs] def __init__(self,
criteria: bc.IConcreteBatchCriteria,
controller_name: str,
scenario_basename: str,
cmdopts: types.Cmdopts) -> None:
self.batch_config_template = pathlib.Path(cmdopts['template_input_file'])
assert self.batch_config_template.is_file(), \
"'{0}' is not a valid file".format(self.batch_config_template)
self.exp_template_stem = self.batch_config_template.stem
self.batch_config_extension = None
self.batch_input_root = pathlib.Path(cmdopts['batch_input_root'])
self.batch_output_root = pathlib.Path(cmdopts['batch_output_root'])
self.controller_name = controller_name
self.scenario_basename = scenario_basename
self.criteria = criteria
self.cmdopts = cmdopts
self.logger = logging.getLogger(__name__)
[docs] def generate_defs(self) -> tp.List[definition.XMLExpDef]:
"""Generate and return the batch experiment definition.
Returns:
A list of experiment definitions (one for each experiment in the
batch).
"""
scaffold_spec = spec.scaffold_spec_factory(self.criteria)
# Create and run generators
defs = []
for i in range(0, scaffold_spec.n_exps):
generator = self._create_exp_generator(i)
self.logger.debug(("Generating scenario+controller changes from "
"generator '%s' for exp%s"),
self.cmdopts['joint_generator'],
i)
defs.append(generator.generate())
return defs
[docs] def _create_exp_generator(self, exp_num: int):
"""
Create the joint scenario+controller generator from command line definitions.
Arguments:
exp_num: Experiment number in the batch
"""
exp_spec = spec.ExperimentSpec(self.criteria, exp_num, self.cmdopts)
template_fpath = exp_spec.exp_input_root / self.exp_template_stem
config_root = pathlib.Path(self.cmdopts['project_config_root'])
scenario = gf.scenario_generator_create(controller=self.controller_name,
exp_spec=exp_spec,
template_input_file=template_fpath,
cmdopts=self.cmdopts)
controller = gf.controller_generator_create(controller=self.controller_name,
config_root=config_root,
cmdopts=self.cmdopts,
exp_spec=exp_spec)
generator = gf.joint_generator_create(scenario=scenario,
controller=controller)
self.cmdopts['joint_generator'] = generator.joint_name
return generator
__api__ = [
'BatchExpDefGenerator',
]