Mapytex/mapytex/calculus/random/core/generate.py

117 lines
3.6 KiB
Python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 lafrite <lafrite@Poivre>
#
# Distributed under terms of the MIT license.
from random import choice
import math
EVAL_FUN = {**math.__dict__}
def complete_variable_configs(
variables, global_config: dict = {}, configs: dict = {}
) -> dict:
"""Completes variables configurations with the global configuration
:param variables: list of random variables to generate
:param global_config: global parameters
:param configs: global parameters
:return: complete variable scope
:example:
>>> completed = complete_variable_configs(["a", "b", "c", "d"],
... global_config={"rejected": [], "min_max": (-10, 10)},
... configs={
... "a": {"rejected": [0, 1]},
... "b": {"min_max": (-5, 0)},
... "c": {"rejected": [2], "min_max": (0, 5)}
... })
>>> completed["a"] == {'rejected': [0, 1], 'min_max': (-10, 10)}
True
>>> completed["b"] == {'rejected': [], 'min_max': (-5, 0)}
True
>>> completed['c'] == {'rejected': [2], 'min_max': (0, 5)}
True
>>> completed['d'] == {'rejected': [], 'min_max': (-10, 10)}
True
"""
complete_configs = configs.copy()
for variable in variables:
try:
complete_configs[variable]
except KeyError:
complete_configs[variable] = global_config
else:
complete_configs[variable] = dict(global_config, **configs[variable])
return complete_configs
def random_generator(
variables: list[str],
conditions: list[str] = [],
global_config: dict = {},
configs: dict = {},
) -> dict[str, int]:
"""Generate random variables
:param variables: list of random variables to generate
:param conditions: condition over variables
:param global_config: global parameters
:param configs: global parameters
:return: dictionnary of generated variables
In variables and configurations, you have access to all math module functions
:example:
>>> gene = random_generator(["a", "b"],
... ["a > 0"],
... {"rejected": [0], "min_max":(-10, 10)},
... {"a": {"rejected": [0, 1]},
... "b": {"min_max": (-5, 0)},
... })
>>> gene["a"] > 0
True
>>> gene["a"] != 0
True
>>> gene["b"] < 0
True
>>> gene = random_generator(["a", "b"],
... ["a % b == 0"],
... {"rejected": [0, 1], "min_max":(-10, 10)}
... )
>>> gene["a"] not in [0, 1]
True
>>> gene["b"] in list(range(-10, 11))
True
>>> gene["a"] % gene["b"]
0
"""
complete_scope = complete_variable_configs(variables, global_config, configs)
choices_list = {
v: list(
set(
range(
complete_scope[v]["min_max"][0], complete_scope[v]["min_max"][1] + 1
)
).difference(complete_scope[v]["rejected"])
)
for v in variables
}
# quantity_choices = reduce(lambda x,y : x*y,
# [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
generate_variable = {v: choice(choices_list[v]) for v in variables}
while not all([eval(c, EVAL_FUN, generate_variable) for c in conditions]):
generate_variable = {v: choice(choices_list[v]) for v in variables}
return generate_variable