Skip to content

Commit

Permalink
Add config_filter param to simulate_factors() (#14)
Browse files Browse the repository at this point in the history
Add a new optional `config_filter` parameter to
`desmod.simulation.simulate_factors()`. When provided, this function
filters the configurations to be simulated.

This can be useful, for example, for just simulating a particular
simulation index, or for taking a random sample from a very large
number of configurations.
  • Loading branch information
bgmerrell authored and jpgrayson committed May 5, 2017
1 parent 84edba4 commit 3bd2ea2
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
9 changes: 8 additions & 1 deletion desmod/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from contextlib import closing
from multiprocessing import cpu_count, Process, Queue
from pprint import pprint
from six.moves import filter
from threading import Thread

import json
import os
import random
Expand Down Expand Up @@ -205,7 +207,7 @@ def simulate(config, top_type, env_type=SimEnvironment, reraise=True,


def simulate_factors(base_config, factors, top_type,
env_type=SimEnvironment, jobs=None):
env_type=SimEnvironment, jobs=None, config_filter=None):
"""Run multi-factor simulations in separate processes.
The `factors` are used to compose specialized config dictionaries for the
Expand All @@ -220,15 +222,20 @@ def simulate_factors(base_config, factors, top_type,
:param top_type: The model's top-level Component subclass.
:param env_type: :class:`SimEnvironment` subclass.
:param int jobs: User specified number of concurent processes.
:param function config_filter:
A function which will be passed a config and returns a bool to filter.
:returns: Sequence of result dictionaries for each simulation.
"""
configs = list(factorial_config(base_config, factors, 'meta.sim.special'))
ws = base_config.setdefault('sim.workspace', os.curdir)
overwrite = base_config.setdefault('sim.workspace.overwrite', False)

for index, config in enumerate(configs):
config['meta.sim.index'] = index
config['meta.sim.workspace'] = os.path.join(ws, str(index))
if config_filter is not None:
configs[:] = filter(config_filter, configs)
if overwrite and os.path.relpath(ws) != os.curdir and os.path.isdir(ws):
shutil.rmtree(ws)
return simulate_many(configs, top_type, env_type, jobs)
Expand Down
19 changes: 19 additions & 0 deletions tests/test_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,25 @@ def test_simulate_factors(config):
result['config']['sim.result.file']))


def test_simulate_factors_only_factor(config):
FACTOR_NUM = 2

def single_factor_filter_fn(cfg):
return cfg['meta.sim.index'] == FACTOR_NUM

factors = [(['sim.seed'], [[1], [2], [3]])]
results = simulate_factors(
config, factors, TopTest, config_filter=single_factor_filter_fn)
assert len(results) == 1
for result in results:
assert result['sim.exception'] is None
assert result['config']['meta.sim.workspace'] == os.path.join(
config['sim.workspace'], str(FACTOR_NUM))
assert os.path.exists(
os.path.join(result['config']['meta.sim.workspace'],
result['config']['sim.result.file']))


def test_simulate_factors_progress(config, capfd):
config['sim.progress.enable'] = True
config['sim.duration'] = '10 us'
Expand Down

0 comments on commit 3bd2ea2

Please sign in to comment.