Feat: move to global_config, configs for generator
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Bertrand Benjamin 2021-10-03 16:52:54 +02:00
parent b2b204c17b
commit 87b6b3ca27
4 changed files with 86 additions and 67 deletions

View File

@ -7,7 +7,7 @@
# Distributed under terms of the MIT license. # Distributed under terms of the MIT license.
""" """
Tools to extract random leafs, random variables, generate random values and Tools to extract random leaves, random variables, generate random values and
fill new trees fill new trees
Flow Flow
@ -17,7 +17,7 @@ Tree with RdLeaf
| |
| Extract rdLeaf | Extract rdLeaf
| |
List of leafs to generate List of leaves to generate
| |
| extract_rv | extract_rv
| |
@ -27,9 +27,9 @@ List random variables to generate
| |
Dictionnary of generated random variables Dictionnary of generated random variables
| |
| Compute leafs | Compute leaves
| |
Dictionnary of computed leafs Dictionnary of computed leaves
| |
| Replace | Replace
| |
@ -46,15 +46,15 @@ Tree with RdLeaf replaced by generated values
/ /
> {a} > {a}
> {a*k} > {a*k}
>>> leafs = rd_t.random_leaf >>> leaves = rd_t.random_leaves
>>> leafs = ['a', 'a*k'] >>> leaves = ['a', 'a*k']
>>> rd_varia = extract_letters(leafs) >>> rd_varia = extract_letters(leaves)
>>> sorted(list(rd_varia)) >>> sorted(list(rd_varia))
['a', 'k'] ['a', 'k']
>>> generated = random_generator(rd_varia, conditions=['a%2+1']) >>> generated = random_generator(rd_varia, conditions=['a%2+1'], global_config={"min_max": (-10, 10), "rejected":[0, 1]})
>>> generated # doctest: +SKIP >>> generated # doctest: +SKIP
{'a': 7, 'k': 4} {'a': 7, 'k': 4}
>>> computed = eval_words(leafs, generated) >>> computed = eval_words(leaves, generated)
>>> computed # doctest: +SKIP >>> computed # doctest: +SKIP
{'a': 7, 'a*k': 28} {'a': 7, 'a*k': 28}
>>> replaced = rd_t.eval_random_leaves(computed) >>> replaced = rd_t.eval_random_leaves(computed)

View File

@ -10,63 +10,60 @@
from random import choice from random import choice
def build_variable_scope(rd_variables, rejected, min_max, variables_scope): def complete_variable_configs(variables, global_config:dict={}, configs:dict={})->dict:
""" Build variables scope from incomplete one """ Completes variables configurations with the global configuration
:param rd_variables: list of random variables to generate :param variables: list of random variables to generate
:param rejected: Rejected values for the generator :param global_config: global parameters
:param min_max: (min, max) limits in between variables will be generated :param configs: global parameters
:param variables_scope: rejected and min_max define for individual variables
:return: complete variable scope :return: complete variable scope
:example: :example:
>>> completed = build_variable_scope(["a", "b", "c", "d"], [0], (-10, 10), >>> completed = complete_variable_configs(["a", "b", "c", "d"],
... {"a": {"rejected": [0, 1]}, ... global_config={"rejected": [], "min_max": (-10, 10)},
... configs={
... "a": {"rejected": [0, 1]},
... "b": {"min_max": (-5, 0)}, ... "b": {"min_max": (-5, 0)},
... "c": {"rejected": [2], "min_max": (0, 5)}}) ... "c": {"rejected": [2], "min_max": (0, 5)}
>>> complete = {'a': {'rejected': [0, 1], 'min_max': (-10, 10)}, ... })
... 'b': {'rejected': [0], 'min_max': (-5, 0)}, >>> completed["a"] == {'rejected': [0, 1], 'min_max': (-10, 10)}
... 'c': {'rejected': [2], 'min_max': (0, 5)}, True
... 'd': {'rejected': [0], 'min_max': (-10, 10)}} >>> completed["b"] == {'rejected': [], 'min_max': (-5, 0)}
>>> completed == complete True
>>> completed['c'] == {'rejected': [2], 'min_max': (0, 5)}
True
>>> completed['d'] == {'rejected': [], 'min_max': (-10, 10)}
True True
""" """
complete_scope = variables_scope.copy() complete_configs = configs.copy()
for v in rd_variables: for variable in variables:
try: try:
complete_scope[v] complete_configs[variable]
except KeyError: except KeyError:
complete_scope[v] = {"rejected": rejected, "min_max": min_max} complete_configs[variable] = global_config
else: else:
try: complete_configs[variable] = dict(global_config, **configs[variable])
complete_scope[v]["rejected"] return complete_configs
except KeyError:
complete_scope[v]["rejected"] = rejected
try:
complete_scope[v]["min_max"]
except KeyError:
complete_scope[v]["min_max"] = min_max
return complete_scope
def random_generator( def random_generator(
rd_variables, conditions=[], rejected=[0], min_max=(-10, 10), variables_scope={} variables:list[str], conditions:list[str]=[], global_config:dict={}, configs:dict={},
): )-> dict[str, int]:
""" Generate random variables """ Generate random variables
:param rd_variables: list of random variables to generate :param variables: list of random variables to generate
:param conditions: condition over variables :param conditions: condition over variables
:param rejected: Rejected values for the generator (default [0]) :param global_config: global parameters
:param min_max: (min, max) limits in between variables will be generated :param configs: global parameters
:param variables_scope: rejected and min_max define for individual variables
:return: dictionnary of generated variables :return: dictionnary of generated variables
:example: :example:
>>> gene = random_generator(["a", "b"], >>> gene = random_generator(["a", "b"],
... ["a > 0"], ... ["a > 0"],
... [0], (-10, 10), ... {"rejected": [0], "min_max":(-10, 10)},
... {"a": {"rejected": [0, 1]}, ... {"a": {"rejected": [0, 1]},
... "b": {"min_max": (-5, 0)}}) ... "b": {"min_max": (-5, 0)},
... })
>>> gene["a"] > 0 >>> gene["a"] > 0
True True
>>> gene["a"] != 0 >>> gene["a"] != 0
@ -75,7 +72,8 @@ def random_generator(
True True
>>> gene = random_generator(["a", "b"], >>> gene = random_generator(["a", "b"],
... ["a % b == 0"], ... ["a % b == 0"],
... [0, 1], (-10, 10)) ... {"rejected": [0, 1], "min_max":(-10, 10)}
... )
>>> gene["a"] not in [0, 1] >>> gene["a"] not in [0, 1]
True True
>>> gene["b"] in list(range(-10, 11)) >>> gene["b"] in list(range(-10, 11))
@ -83,8 +81,8 @@ def random_generator(
>>> gene["a"] % gene["b"] >>> gene["a"] % gene["b"]
0 0
""" """
complete_scope = build_variable_scope( complete_scope = complete_variable_configs(
rd_variables, rejected, min_max, variables_scope variables, global_config, configs
) )
choices_list = { choices_list = {
v: list( v: list(
@ -94,17 +92,17 @@ def random_generator(
) )
).difference(complete_scope[v]["rejected"]) ).difference(complete_scope[v]["rejected"])
) )
for v in rd_variables for v in variables
} }
# quantity_choices = reduce(lambda x,y : x*y, # quantity_choices = reduce(lambda x,y : x*y,
# [len(choices_list[v]) for v in choices_list]) # [len(choices_list[v]) for v in choices_list])
# TODO: améliorer la méthode de rejet avec un cache |dim. mai 12 17:04:11 CEST 2019 # TODO: améliorer la méthode de rejet avec un cache |dim. mai 12 17:04:11 CEST 2019
generate_variable = {v: choice(choices_list[v]) for v in rd_variables} generate_variable = {v: choice(choices_list[v]) for v in variables}
while not all([eval(c, __builtins__, generate_variable) for c in conditions]): while not all([eval(c, __builtins__, generate_variable) for c in conditions]):
generate_variable = {v: choice(choices_list[v]) for v in rd_variables} generate_variable = {v: choice(choices_list[v]) for v in variables}
return generate_variable return generate_variable

View File

@ -1,5 +1,6 @@
from ...core.tree import MutableTree, Tree from ...core.tree import MutableTree, Tree
from .grammar import extract_letters from .grammar import extract_letters, eval_words
from .generate import random_generator
from .str2 import rdstr2 from .str2 import rdstr2
class RandomTree(MutableTree): class RandomTree(MutableTree):
@ -35,23 +36,18 @@ class RandomTree(MutableTree):
""" """
str_2_mut_tree = rdstr2(cls.sink) str_2_mut_tree = rdstr2(cls.sink)
return str_2_mut_tree(expression) return str_2_mut_tree(expression)
def generate(self, conditions:list[str]=[], rejected:list[int]=[0, 1], min_max:tuple[int]=(-10, 10),scopes:dict={}) -> Tree:
""" Generate a random version of self """
pass
@property @property
def random_leaf(self) -> list[str]: def random_leaves(self) -> list[str]:
""" Get list of random leaves """ Get list of random leaves
:example: :example:
>>> from .leaf import RdLeaf >>> from .leaf import RdLeaf
>>> random_tree = RandomTree("+", RdLeaf("a"), RdLeaf("a*k")) >>> random_tree = RandomTree("+", RdLeaf("a"), RdLeaf("a*k"))
>>> random_tree.random_leaf >>> random_tree.random_leaves
['a', 'a*k'] ['a', 'a*k']
>>> random_tree = RandomTree("+", RdLeaf("a"), 2) >>> random_tree = RandomTree("+", RdLeaf("a"), 2)
>>> random_tree.random_leaf >>> random_tree.random_leaves
['a'] ['a']
""" """
rd_leafs = [] rd_leafs = []
@ -78,7 +74,7 @@ class RandomTree(MutableTree):
>>> random_tree.random_value >>> random_tree.random_value
{'a'} {'a'}
""" """
return extract_letters(self.random_leaf) return extract_letters(self.random_leaves)
def eval_random_leaves(self, leaves_value:dict[str, int]): def eval_random_leaves(self, leaves_value:dict[str, int]):
@ -102,3 +98,15 @@ class RandomTree(MutableTree):
except AttributeError: except AttributeError:
return leaf return leaf
return self.map_on_leaf(replace) return self.map_on_leaf(replace)
def generate(self, conditions:list[str]=[], config:dict={} , configs:dict={}) -> Tree:
""" Generate a random version of self
:param conditions: list of conditions
:param config: global configuration for generated values
:param configs: specific configuration for each generated values
"""
generated_values = random_generator(self.random_values, config, configs)
leaves = eval_words(self.random_leaves, generated_values)
return self.eval_random_leaves(leaves)

View File

@ -12,7 +12,12 @@ This function ignores tree structure and works with lists
from .core.generate import random_generator from .core.generate import random_generator
from .core.grammar import extract_letters, eval_words from .core.grammar import extract_letters, eval_words
def list_generator(var_list, conditions=[], rejected=[0], min_max=(-10, 10), variables_scope={}, dictionnary=False): DEFAUTL_CONFIG = {
"rejected": [0],
"min_max": (-10, 10),
}
def list_generator(var_list:list[str], conditions:list[str]=[], global_config:dict={}, configs:dict={})->list[int]:
""" Generate random computed values from the list """ Generate random computed values from the list
:param rd_variables: list of random variables to generate (can be computed value - "a*b") :param rd_variables: list of random variables to generate (can be computed value - "a*b")
@ -20,7 +25,6 @@ def list_generator(var_list, conditions=[], rejected=[0], min_max=(-10, 10), var
:param rejected Rejected values for the generator (default [0]) :param rejected Rejected values for the generator (default [0])
:param min_max: (min, max) limits in between variables will be generated :param min_max: (min, max) limits in between variables will be generated
:param variables_scope: rejected and min_max define for individual variables :param variables_scope: rejected and min_max define for individual variables
:param dictionnary: the return value will be a dictionnary with var_list as keys (default False)
:return: dictionnary of generated variables :return: dictionnary of generated variables
:example: :example:
@ -33,12 +37,21 @@ def list_generator(var_list, conditions=[], rejected=[0], min_max=(-10, 10), var
-20 -20
>>> a, b # doctest: +SKIP >>> a, b # doctest: +SKIP
5, -4 5, -4
>>> list_generator(["a", "a*b", "b", "c"], dictionnary=True) # doctest: +SKIP >>> a, ab, b, c = list_generator(["a", "a*b", "b", "c"], conditions=["a-b==0"])
{'a': -3, 'a*b': 18, 'b': -6, 'c': -4} >>> a - b == 0
True
>>> a, ab, b, c = list_generator(["a", "a*b", "b", "c"], global_config={"rejected": [2, 3, 5, 7]})
>>> a not in [2, 3, 5, 7]
True
>>> b not in [2, 3, 5, 7]
True
>>> c not in [2, 3, 5, 7]
True
>>> a, ab, b, c = list_generator(["a", "a*b", "b", "c"], configs={"a": {"rejected": [2, 3, 5, 7]})
>>> a not in [2, 3, 5, 7]
True
""" """
rv = extract_letters(var_list) rv = extract_letters(var_list)
rv_gen = random_generator(rv, conditions, rejected, min_max, variables_scope) rv_gen = random_generator(rv, conditions, dict(DEFAUTL_CONFIG, **global_config), variables_scope)
generated = eval_words(var_list, rv_gen) generated = eval_words(var_list, rv_gen)
if dictionnary:
return generated
return [generated[v] for v in var_list] return [generated[v] for v in var_list]