# -*- coding: utf-8 -*-
# pylint: disable: line-too-long
"""
Created on Mon Mar 23 21:14:59 2015.
@author: Morten
"""
import types
import logging
from pprint import pprint, pformat # noqa
from copy import deepcopy
from collections.abc import MutableSequence
import numpy as np
from anypytools.tools import define2str, path2str, array2anyscript
logger = logging.getLogger("abt.anypytools")
__all__ = [
"MacroCommand",
"Load",
"SetValue",
"SetValue_random",
"Dump",
"SaveDesign",
"LoadDesign",
"SaveValues",
"LoadValues",
"UpdateValues",
"OperationRun",
"SaveData",
]
def _isgenerator(x):
return isinstance(x, types.GeneratorType)
def _batch(iterable, n=1):
length = len(iterable)
for ndx in range(0, length, n):
yield iterable[ndx : min(ndx + n, length)]
[docs]class MacroCommand(object):
"""Class for custom macro commands.
This class also serves as base class for other macro commands.
Examples
--------
>>> mc = MacroCommand('operation "Main.MyStudy.InverseDynamics"') )
>>> print(mc)
operation "Main.MyStudy.InverseDynamics"
"""
def __init__(self, command):
if not isinstance(command, list):
self.cmd = [command]
else:
self.cmd = command
def __repr__(self):
return self.get_macro(0)
[docs] def get_macro(self, index, **kwarg):
"""Create a string representation of the macro.
Parameters
----------
index : int
The index for the macro beeing generated. Some child classes
use the index to generate different macros depending on the
index.
Returns
-------
string
A string with the AnyScript macro
"""
return "\n".join(self.cmd)
[docs]class Load(MacroCommand):
"""Create a load macro command.
Parameters
----------
filename : str
Path of the file to load
defs : dict
Dictionary of defines statements to set during load
paths : dict
Dictionary of path staements to set during load
Examples
--------
>>> Load('model.main.any')
load "model.main.any"
>>> paths = {'DATA':'c:/MyModel/Data'}
>>> defines = {'EXCLUDE_ARMS':None, 'N_STEP':20}
>>> Load('c:/MyModel/model.main.any', defines, paths)
load "c:/MyModel/model.main.any" -def EXCLUDE_ARMS="" -def N_STEP="20" -p DATA=---"c:/MyModel/Data"
>>> mcr = AnyMacro( Load('model_{id}.main.any'), counter_token = '{id}')
>>> mcr.create_macros(3)
[[u'load "model_0.main.any"'],
[u'load "model_1.main.any"'],
[u'load "model_2.main.any"']]
"""
def __init__(self, filename, defs={}, paths={}):
self.filename = filename
self.defs = defs.copy()
self.paths = paths.copy()
[docs] def get_macro(self, index, **kwarg):
cmd = [f'load "{self.filename}"']
for key in sorted(self.defs):
value = self.defs[key]
cmd.append(define2str(key, value))
for key in sorted(self.paths):
value = self.paths[key]
cmd.append(path2str(key, value))
return " ".join(cmd)
[docs]class SetValue(MacroCommand):
"""Create 'Set Value' classoperation macro command.
Parameters
----------
var : string
An AnyScript variable.
value : number or list of number
A value or list of values to assign to the AnyScript variable.
Examples
---------
Set a single values:
>>> SetValue('Main.Study.myvar1', 23.1)
classoperation Main.Study.myvar1 "Set Value" --value="23.1"
>>> SetValue('Main.Study.myvar2', np.array([2,3,4]))
classoperation Main.Study.myvar2 "Set Value" --value="{2,3,4}"
Set variable across different macros
>>> SetValue('Main.Study.myvar1',[1,2,3])
classoperation Main.Study.myvar1 "Set Value" --value="1"
classoperation Main.Study.myvar1 "Set Value" --value="2"
classoperation Main.Study.myvar1 "Set Value" --value="3"
Here is a elaborate example:
>>> mg = AnyMacro( Load('MyModel.main.any'),
SetValue('Main.Study.myvar1',[1,2]),
OperationRun('Main.Study.InverseDynamics') )
>>> mg.number_of_macros = 2
[['load "MyModel.main.any"',
'classoperation Main.Study.myvar1 "Set Value" --value="1"',
'operation Main.Study.InverseDynamics',
'run'],
['load "MyModel.main.any"',
'classoperation Main.Study.myvar1 "Set Value" --value="2"',
'operation Main.Study.InverseDynamics',
'run']]
If we generate more macros that there are values then the values are just
repeated
>>> mg.number_of_macros = 4
>>> mg
[['load "MyModel.main.any"',
'classoperation Main.Study.myvar1 "Set Value" --value="1"',
'operation Main.Study.InverseDynamics',
'run'],
['load "MyModel.main.any"',
'classoperation Main.Study.myvar1 "Set Value" --value="2"',
'operation Main.Study.InverseDynamics',
'run'],
['load "MyModel.main.any"',
'classoperation Main.Study.myvar1 "Set Value" --value="1"',
'operation Main.Study.InverseDynamics',
'run'],
['load "MyModel.main.any"',
'classoperation Main.Study.myvar1 "Set Value" --value="2"',
'operation Main.Study.InverseDynamics',
'run']]
"""
def __init__(self, var, value):
self.var = var
self.value = value
def __repr__(self):
if isinstance(self.value, list):
n_elem = len(self.value)
else:
n_elem = 1
return "\n".join([self.get_macro(i) for i in range(n_elem)])
[docs] def get_macro(self, index, **kwarg):
if isinstance(self.value, list):
val = self.value[index % len(self.value)]
else:
val = self.value
return self._format_macro(val)
def _format_macro(self, val):
if isinstance(val, np.ndarray):
val = array2anyscript(val)
elif isinstance(val, float):
val = f"{val:.12g}"
elif isinstance(val, int):
val = f"{val:d}"
return f'classoperation {self.var} "Set Value" --value="{val}"'
[docs]class SetValue_random(SetValue):
"""Create a 'Set Value' macro command from a distribution.
The value is connected to a distibution in scipy.stats.distributions.
Parameters
----------
var : str
An AnyScript variable.
frozen_distribution : <scipy.stats.distributions.rv_frozen>
A frozen distribution from scipy.stats.distributions
default_lower_tail_probability : float
The lower tail probability of the default value. Defaults to 0.5 which
is the mean value.
Examples
--------
Creating normal macros will use the default values. Usually the 50 percentile
(mean values).
>>> np.random.seed(1)
>>> from scipy.stats.distributions import logistic, norm
>>> log_dist = logistic( loc= [1,3,4],scale = [0.1,0.5,1] )
>>> norm_dist = norm( loc= [0,0,0],scale = [0.1,0.5,1] )
>>> cmd = [SetValue_random('Main.MyVar1', log_dist), SetValue_random('Main.MyVar2', norm_dist) ]
>>> mg = AnyMacro(cmd, number_of_macros = 3)
>>> mg
[['classoperation Main.MyVar1 "Set Value" --value="{0,0,0}"',
'classoperation Main.MyVar2 "Set Value" --value="{1,3,4}"'],
['classoperation Main.MyVar1 "Set Value" --value="{0,0,0}"',
'classoperation Main.MyVar2 "Set Value" --value="{1,3,4}"'],
['classoperation Main.MyVar1 "Set Value" --value="{0,0,0}"',
'classoperation Main.MyVar2 "Set Value" --value="{1,3,4}"']]
Values can be sampled randomly in a 'Monte Carlo' fashion. Note that the
first value is still the defaut mean values
>>> mg.create_macros_MonteCarlo()
[['classoperation Main.MyVar1 "Set Value" --value="{0,0,0}"',
'classoperation Main.MyVar2 "Set Value" --value="{1,3,4}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.0209517840916,0.291902872134,-3.68494766954}"',
'classoperation Main.MyVar2 "Set Value" --value="{0.916378512121,2.11986245798,1.71459079162}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.0891762169545,-0.198666812922,-0.261723075945}"',
'classoperation Main.MyVar2 "Set Value" --value="{1.01555799978,2.83695956934,4.7778636562}"']]
Values can also be sampled with a Latin Hyper Cube sampler.
>>> mg.create_macros_LHS()
[['classoperation Main.MyVar1 "Set Value" --value="{0.0928967116493,-0.591418725401,-0.484696993931}"',
'classoperation Main.MyVar2 "Set Value" --value="{1.01049414425,2.46211329129,5.73806916203}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.0166741228961,0.707722119582,-0.294180629253}"',
'classoperation Main.MyVar2 "Set Value" --value="{1.11326829265,2.66016732923,4.28054911097}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.20265197275,0.114947152258,0.924796936287}"',
'classoperation Main.MyVar2 "Set Value" --value="{0.806864877696,4.4114188826,2.93941843565}"']]
"""
def __init__(self, var, frozen_distribution, default_lower_tail_probability=0.5):
from scipy.stats.distributions import rv_frozen
self.var = var
if not isinstance(frozen_distribution, rv_frozen):
raise TypeError(
"frozen_distribution must be frozen distribtuion from \
scipy.stats.distributions"
)
self.rv = frozen_distribution
self.meanvalue = frozen_distribution.mean()
if isinstance(self.meanvalue, np.ndarray):
self.shape = self.meanvalue.shape
self.n_factors = np.prod(self.shape)
self.default_lower_tail_probability = (
default_lower_tail_probability * np.ones(self.shape)
)
else:
self.shape = None
self.n_factors = 1
self.default_lower_tail_probability = default_lower_tail_probability
def __repr__(self):
return self.get_macro(0)
[docs] def get_macro(self, index, lower_tail_probability=None, **kwarg):
if lower_tail_probability is None:
lower_tail_probability = self.default_lower_tail_probability
if self.shape is None and isinstance(lower_tail_probability, np.ndarray):
lower_tail_probability = lower_tail_probability[0]
val = self.rv.ppf(lower_tail_probability).reshape(self.shape)
# Replace any nan from ppf function with actual sampled values.
if np.any(np.isnan(val)):
val[np.isnan(val)] = self.rv.rvs()[np.isnan(val)]
return self._format_macro(val)
[docs]class Dump(MacroCommand):
"""Create a Dump classoperation macro command.
Parameters
----------
var : str or list of str
The anyscript values to create a 'Dump' macro command for
include_in_macro: int or list of int
Specifices in which macros [0,1,2....NumberOfMacros] to include the
dump command.
If None, the command is included in all macros.
Examples
---------
>>> Dump('Main.Study.myvar1')
classoperation Main.Study.myvar1 "Dump"
Only include the dump command in the two first macro
>>> mg = AnyMacro(number_of_macros = 5)
>>> mg.append(Load('mymodel.main.any'))
>>> mg.append(Dump('Main.Study.myvar1', include_in_macro = [0,1]))
>>> mg
[['load "mymodel.main.any"', 'classoperation Main.Study.myvar1 "Dump"'],
['load "mymodel.main.any"', 'classoperation Main.Study.myvar1 "Dump"'],
['load "mymodel.main.any"'],
['load "mymodel.main.any"'],
['load "mymodel.main.any"']]
"""
def __init__(self, var, include_in_macro=None):
if not isinstance(var, list):
self.var_list = [var]
else:
self.var_list = var
self._include_in_macro = include_in_macro
[docs] def get_macro(self, index, **kwarg):
cmd = []
if self._include_in_macro is None or index in self._include_in_macro:
for var in self.var_list:
cmd.append(f'classoperation {var} "Dump"')
return "\n".join(cmd)
[docs]class SaveDesign(MacroCommand):
"""Create a Save Design classoperation macro command.
Parameters
----------
operation : str
The AnyScript operation
filename : str
The filename in which to save the design
Examples
--------
>>> SaveDesign('Main.MyStudy.Kinematics', 'c:/design.txt')
classoperation Main.MyStudy.Kinematics "Save design" --file="c:/design.txt"
"""
def __init__(self, operation, filename):
self.filename = filename
self.operation = operation
[docs] def get_macro(self, index, **kwarg):
return f'classoperation {self.operation} "Save design" --file="{self.filename}"'
[docs]class LoadDesign(MacroCommand):
"""Create a Load Design classoperation macro command.
Parameters
----------
operation : str
The AnyScript operation
filename : str
The file in which to load the design from
Examples
--------
>>> LoadDesign('Main.MyStudy.Kinematics', 'c:/design.txt')
classoperation Main.MyStudy.Kinematics "Load design" --file="c:/design.txt"
"""
def __init__(self, operation, filename):
self.filename = filename
self.operation = operation
[docs] def get_macro(self, index, **kwarg):
return f'classoperation {self.operation} "Load design" --file="{self.filename}"'
[docs]class SaveValues(MacroCommand):
"""Create a Save Values classoperation macro command.
Parameters
----------
filename : str
The anyset file to save the values to
Examples
--------
>>> SaveValues('c:/values.anyset')
classoperation Main "Save Values" --file="c:/values.anyset"
"""
def __init__(self, filename):
self.filename = filename
[docs] def get_macro(self, index, **kwarg):
return f'classoperation Main "Save Values" --file="{self.filename}"'
[docs]class SaveData(MacroCommand):
"""Create a Save Data classoperation macro command.
This macro operation will save all data from a study to a
HDF5 file.
Parameters
----------
operation : str
Operation to save the h5 from
filename : str
The anyset file to save the values to
Examples
--------
>>> SaveData('Main.Study', 'output.anydata.h5')
classoperation Main.Study.Output "Save data" --type="Deep" --file="output.anydata.h5"
"""
def __init__(self, operation, filename):
self.filename = filename
self.opeation = operation
[docs] def get_macro(self, index, **kwarg):
macro_str = 'classoperation {}.Output "Save data" --type="Deep" --file="{}"'
return macro_str.format(self.opeation, self.filename)
[docs]class LoadValues(MacroCommand):
"""Create a Load Values classoperation macro command.
Parameters
----------
filename : str
The anyset file to load the values from.
Examples
--------
>>> LoadValues('c:/values.anyset')
classoperation Main "Load Values" --file="c:/values.anyset"
"""
def __init__(self, filename):
self.filename = filename
[docs] def get_macro(self, index, **kwarg):
return f'classoperation Main "Load Values" --file="{self.filename}"'
[docs]class UpdateValues(MacroCommand):
"""Create an 'Update Values' classoperation macro command.
Examples
--------
>>> UpdateValues()
classoperation Main "Update Values"
"""
def __init__(self):
pass
[docs] def get_macro(self, index, **kwarg):
return 'classoperation Main "Update Values"'
[docs]class OperationRun(MacroCommand):
"""Create a macro command to select and run an operation.
Examples
--------
>>> OperationRun('Main.MyStudy.Kinematics')
>>> pprint( mg.generate_macros())
operation Main.MyStudy.Kinematics
run
>>> mg = AnyMacro(Load('my_model.main.any'),
OperationRun('Main.MyStudy.Kinematics'))
>>> mg.create_macros()
[[u'load "my_model.main.any"', u'operation Main.MyStudy.Kinematics', u'run']]
"""
def __init__(self, operation):
self.operation = operation
[docs] def get_macro(self, index, **kwarg):
return f"operation {self.operation}" + "\n" + "run"
[docs]class AnyMacro(MutableSequence):
"""
Class to generate multiple macros.
Use the class to contruct multiple anyscript macros from a single macro.
E.g. for parameter studies, Monte Carlo, Latin Hyper Cube studies.
Parameters
----------
maco_commands : list or positional arguments
A list of macro command classes. These may also be given a arbitrary number
of positional arguments.
counter_token : str
A string in the macro commands which will be replace with a counter
for every macro generated
number_of_macros : int
The default number of macros which are created. This can be overruled when
calling the AnyMacro.create_macros() function. Defults to 1.
seed : int or array_like
A constant seed value used which will be used every time macros are created.
Must be convertable to 32 bit unsigned integers.
Returns
-------
An AnyMacro instance
A Macro object for constructing the macro.
Examples
--------
>>> mg = AnyMacro(number_of_macros = 22)
>>> mg.append( Load('c:/MyModel/model.main.any', defs = {}, paths = {} ) )
>>> mg.append( SetValue('Main.myvar', 12.3) )
>>> mg.extend( [RunOperation('Main.Study.Kinematics'),
Dump('Main.Study.Output.MyVar') ] )
>>> mg
[['load "c:/MyModel/model.main.any"',
'classoperation Main.myvar "Set Value" --value="12.3"',
'operation Main.Study.Kinematics',
'run',
'classoperation Main.Study.Output.MyVar "Dump"'],
['load "c:/MyModel/model.main.any"',
'classoperation Main.myvar "Set Value" --value="12.3"',
'operation Main.Study.Kinematics',
'run',
'classoperation Main.Study.Output.MyVar "Dump"']]
>>> mg = AnyMacro( number_of_macros = 3, counter_token='{COUNTER}' )
>>> mg.append(Load('c:/MyModel/model_{COUNTER}_.main.any') )
>>> pprint(mg.create_macros())
[['load "c:/MyModel/model_0_.main.any"'],
['load "c:/MyModel/model_1_.main.any"'],
['load "c:/MyModel/model_2_.main.any"']]
"""
def __init__(self, *args, **kwargs): # number_of_macros=1, counter_token = None ):
super(AnyMacro, self).__init__()
if len(args) == 0:
self._list = list()
else:
if len(args) == 1 and isinstance(args[0], list):
args = args[0]
for arg in args:
if not isinstance(arg, MacroCommand):
raise ValueError("Argument must be valid macro command classes")
self._list = list(args)
self.seed = kwargs.pop("seed", None)
self.number_of_macros = kwargs.pop("number_of_macros", 1)
self.counter_token = kwargs.pop("counter_token", None)
def __mul__(self, other):
if not isinstance(other, (int, float)):
raise NotImplementedError("operator must be integer")
mg = deepcopy(self)
mg.number_of_macros = mg.number_of_macros * round(other)
return mg
__rmul__ = __mul__
def __len__(self):
return len(self._list)
def __getitem__(self, ii):
return self._list[ii]
def __delitem__(self, ii):
del self._list[ii]
def __setitem__(self, ii, val):
self._list[ii] = val
return self._list[ii]
def __str__(self):
return self.__repr__()
def __repr__(self):
return pformat(self.create_macros())
[docs] def insert(self, ii, val):
self._list.insert(ii, val)
[docs] def append(self, val):
list_idx = len(self._list)
self.insert(list_idx, val)
[docs] def create_macros(self, number_of_macros=None, batch_size=None):
"""Generate a given number of macros.
The function return its output either as list (batch_size = None) or in batches
as generator object (memory efficient when generating many macros)
Parameters
----------
number_of_macros : int (Optional)
The number of macro to create.
batch_size : int (Optional)
If specified the function will return a generator which creates macros in
batches.
Returns
-------
list or generator
A list macros or a generator which creates macros in batches
Examples
--------
>>> from anypytools import AnyMacro
>>> from anypytools.macro_commands import *
>>> macro = [
... Load('c:/Model.main.any'),
... OperationRun('Main.study.Kinematics'),
... ]
>>> mg = AnyMacro(macro, number_of_macros=4)
>>> macrolist = mg.create_macros()
>>> pprint(macrolist)
[['load "c:/Model.main.any"', 'operation Main.study.Kinematics', 'run'],
['load "c:/Model.main.any"', 'operation Main.study.Kinematics', 'run'],
['load "c:/Model.main.any"', 'operation Main.study.Kinematics', 'run'],
['load "c:/Model.main.any"', 'operation Main.study.Kinematics', 'run']]
Generate macros in batches
>>> mg = AnyMacro([Load('c:/Model.main.any')], number_of_macros = 6)
>>> macro_gen = mg.create_macros(batch_size=2)
>>> for i, macros in enumerate( macro_gen ):
... print('Batch ', i)
... pprint(macros)
Batch 0
[['load "c:/Model.main.any"'], ['load "c:/Model.main.any"']]
Batch 1
[['load "c:/Model.main.any"'], ['load "c:/Model.main.any"']]
Batch 2
[['load "c:/Model.main.any"'], ['load "c:/Model.main.any"']]
"""
if batch_size is not None:
return _batch(self.create_macros(number_of_macros), n=batch_size)
if number_of_macros is None:
number_of_macros = self.number_of_macros
if self.seed is not None:
np.random.seed(self.seed)
macro_list = []
for macro_idx in range(number_of_macros):
macro = []
for elem in self:
mcr = elem.get_macro(macro_idx)
if self.counter_token:
mcr = mcr.replace(self.counter_token, str(macro_idx))
if mcr != "":
macro.extend(mcr.split("\n"))
macro_list.append(macro)
return macro_list
[docs] def create_macros_MonteCarlo(self, number_of_macros=None, batch_size=None): # noqa
"""Generate AnyScript macros for monte carlos studies.
The function returns macros for Monte Carlo parameter studies. This methods
extends the `create_macros` methods with functionality to randomly vary
parameters across macros.
Values added with `SetValue_random` class are sampled randomly in a
'Monte Carlo' fashion. Note that the values of the first macro
is the defaut mean value.
Parameters
----------
number_of_macros : int (Optional)
The number of macro to create.
batch_size : int (Optional)
If specified the function will return a generator which creates macros in
batches.
Returns
-------
list or generator
A list macros or a generator which creates macros in batches
Examples
--------
>>> np.random.seed(1)
>>> from scipy.stats.distributions import logistic, norm
>>> log_dist = logistic( loc= [1,3,4],scale = [0.1,0.5,1] )
>>> norm_dist = norm( loc= [0,0,0],scale = [0.1,0.5,1] )
>>> cmd = [SetValue_random('Main.MyVar1', log_dist), SetValue_random('Main.MyVar2', norm_dist) ]
>>> mg = AnyMacro(cmd, number_of_macros = 3)
>>> mg.create_macros_MonteCarlo()
[['classoperation Main.MyVar1 "Set Value" --value="{0,0,0}"',
'classoperation Main.MyVar2 "Set Value" --value="{1,3,4}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.0209517840916,0.291902872134,-3.68494766954}"',
'classoperation Main.MyVar2 "Set Value" --value="{0.916378512121,2.11986245798,1.71459079162}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.0891762169545,-0.198666812922,-0.261723075945}"',
'classoperation Main.MyVar2 "Set Value" --value="{1.01555799978,2.83695956934,4.7778636562}"']]
"""
if batch_size is not None:
return _batch(self.create_macros_MonteCarlo(number_of_macros), batch_size)
if number_of_macros is None:
number_of_macros = self.number_of_macros
if self.seed is not None:
np.random.seed(self.seed)
macro_list = []
for macro_idx in range(number_of_macros):
macro = []
lhs_idx = 0
for elem in self:
if isinstance(elem, SetValue_random):
if macro_idx == 0:
lower_tail_probability = (
None # First macro get the default values
)
else:
lower_tail_probability = np.random.random(elem.n_factors)
mcr = elem.get_macro(macro_idx, lower_tail_probability)
lhs_idx += elem.n_factors
else:
mcr = elem.get_macro(macro_idx)
if self.counter_token:
mcr = mcr.replace(self.counter_token, str(macro_idx))
if mcr != "":
macro.extend(mcr.split("\n"))
macro_list.append(macro)
return macro_list
[docs] def create_macros_LHS(
self,
number_of_macros=None,
criterion=None, # noqa
iterations=None,
batch_size=None,
append_default=False,
):
"""Generate AnyScript macros for Latin Hyper Cube Studies studies.
Generates AnyScript macros for parameter studies using Latin hyper cube
sampling. The macros added with the `SetValue_random` are created with
with Latin Hypercube Sampling (LHS) of the parameter space. The number
of generated macros determines the number of LHS samples.
The method uses the pyDOE package to generate the LHS data.
Parameters
----------
number_of_macros : int (Optional)
The number of macro to create.
batch_size : int (Optional)
If specified the function will return a generator which creates macros in
batches.
criterion : {None, 'c', 'm', 'cm', 'corr'}
A a string that specifies how points are sampled
(see: http://pythonhosted.org/pyDOE/randomized.html)
`None` (Default) points are randomizes within the intervals.
"center" or "c" center the points within the sampling intervals
"maximin" or "m": maximize the minimum distance between points, but place
the point in a randomized location within its interval
"centermaximin" or "cm": same as “maximin”, but centered within the intervals
"corr" minimize the maximum correlation coefficient
iterations : int
Specifies how many iterations are used to accomplished the selected criterion
append_default : bool
If True a macro with default (mean) values is appended to the returned list
of returned macros
Returns
-------
list or generator
A list macros or a generator which creates macros in batches
Examples
--------
>>> np.random.seed(1)
>>> from scipy.stats.distributions import logistic, norm
>>> log_dist = logistic( loc= [1,3,4],scale = [0.1,0.5,1] )
>>> norm_dist = norm( loc= [0,0,0],scale = [0.1,0.5,1] )
>>> cmd = [SetValue_random('Main.MyVar1', log_dist), SetValue_random('Main.MyVar2', norm_dist) ]
>>> mg = AnyMacro(cmd, number_of_macros = 3)
>>> mg.create_macros_LHS()
[['classoperation Main.MyVar1 "Set Value" --value="{0.0928967116493,-0.591418725401,-0.484696993931}"',
'classoperation Main.MyVar2 "Set Value" --value="{1.01049414425,2.46211329129,5.73806916203}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.0166741228961,0.707722119582,-0.294180629253}"',
'classoperation Main.MyVar2 "Set Value" --value="{1.11326829265,2.66016732923,4.28054911097}"'],
['classoperation Main.MyVar1 "Set Value" --value="{-0.20265197275,0.114947152258,0.924796936287}"',
'classoperation Main.MyVar2 "Set Value" --value="{0.806864877696,4.4114188826,2.93941843565}"']]
""" # noqa
try:
import pyDOE
except ImportError:
raise ImportError("The pyDOE package must be install to use this class")
if batch_size is not None:
return _batch(
self.create_macros_LHS(number_of_macros, criterion, iterations),
n=batch_size,
)
if number_of_macros is None:
number_of_macros = self.number_of_macros
if self.seed is not None:
np.random.seed(self.seed)
factors = sum([e.n_factors for e in self if isinstance(e, SetValue_random)])
lhs_matrix = pyDOE.lhs(
factors, number_of_macros, criterion=criterion, iterations=iterations
)
macro_list = []
for macro_idx in range(number_of_macros):
macro = []
lhs_idx = 0
for elem in self:
if isinstance(elem, SetValue_random):
lhs_val = lhs_matrix[macro_idx, lhs_idx : lhs_idx + elem.n_factors]
mcr = elem.get_macro(macro_idx, lower_tail_probability=lhs_val)
lhs_idx += elem.n_factors
else:
mcr = elem.get_macro(macro_idx)
if self.counter_token:
mcr = mcr.replace(self.counter_token, str(macro_idx))
if len(mcr) > 0:
macro.extend(mcr.split("\n"))
macro_list.append(macro)
if append_default:
macro = []
for elem in self:
mcr = elem.get_macro(number_of_macros)
if self.counter_token:
mcr = mcr.replace(self.counter_token, str(number_of_macros))
if len(mcr) > 0:
macro.extend(mcr.split("\n"))
macro_list.append(macro)
return macro_list
if __name__ == "__main__":
# mg = PertubationMacroGenerator()
# mg.add_set_value_designvar('test',1)
# mg.add_set_value_designvar('test',2)
#
# pprint(mg.generate_macros())
#
import pytest
pytest.main(str("generate_macros.py --doctest-modules"))