#! /usr/bin/env python # -*- coding: utf-8 -*- # vim:fenc=utf-8 # # Copyright © 2017 lafrite # # Distributed under terms of the MIT license. from random import choice def build_variable_scope(rd_variables, rejected, min_max, variables_scope): """ Build variables scope from incomplete one :param rd_variables: list of random variables to generate :param rejected: Rejected values for the generator :param min_max: (min, max) limits in between variables will be generated :param variables_scope: rejected and min_max define for individual variables :return: complete variable scope :example: >>> completed = build_variable_scope(["a", "b", "c", "d"], [0], (-10, 10), ... {"a": {"rejected": [0, 1]}, ... "b": {"min_max": (-5, 0)}, ... "c": {"rejected": [2], "min_max": (0, 5)}}) >>> complete = {'a': {'rejected': [0, 1], 'min_max': (-10, 10)}, ... 'b': {'rejected': [0], 'min_max': (-5, 0)}, ... 'c': {'rejected': [2], 'min_max': (0, 5)}, ... 'd': {'rejected': [0], 'min_max': (-10, 10)}} >>> completed == complete True """ complete_scope = variables_scope.copy() for v in rd_variables: try: complete_scope[v] except KeyError: complete_scope[v] = {"rejected": rejected, "min_max": min_max} else: try: complete_scope[v]["rejected"] 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( rd_variables, conditions=[], rejected=[0], min_max=(-10, 10), variables_scope={} ): """ Generate random variables :param rd_variables: list of random variables to generate :param conditions: condition over variables :param rejected: Rejected values for the generator (default [0]) :param min_max: (min, max) limits in between variables will be generated :param variables_scope: rejected and min_max define for individual variables :return: dictionnary of generated variables :example: >>> gene = random_generator(["a", "b"], ... ["a > 0"], ... [0], (-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"], ... [0, 1], (-10, 10)) >>> gene["a"] not in [0, 1] True >>> gene["b"] in list(range(-10, 11)) True >>> gene["a"] % gene["b"] 0 """ complete_scope = build_variable_scope( rd_variables, rejected, min_max, variables_scope ) 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 rd_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 rd_variables} while not all([eval(c, __builtins__, generate_variable) for c in conditions]): generate_variable = {v: choice(choices_list[v]) for v in rd_variables} return generate_variable